Rit*_*XPD 29 angular2-forms angular
我想创建一个可以与FormBuilder API一起使用的自定义输入组件.如何formControlName
在组件内添加?
模板:
<label class="custom-input__label"
*ngIf="label">
{{ label }}
</label>
<input class="custom-input__input"
placeholder="{{ placeholder }}"
name="title" />
<span class="custom-input__message"
*ngIf="message">
{{ message }}
</span>
Run Code Online (Sandbox Code Playgroud)
零件:
import {
Component,
Input,
ViewEncapsulation
} from '@angular/core';
@Component({
moduleId: module.id,
selector: 'custom-input',
host: {
'[class.custom-input]': 'true'
},
templateUrl: 'input.component.html',
styleUrls: ['input.component.css'],
encapsulation: ViewEncapsulation.None,
})
export class InputComponent {
@Input() label: string;
@Input() message: string;
@Input() placeholder: string;
}
Run Code Online (Sandbox Code Playgroud)
用法:
<custom-input label="Title"
formControlName="title" // Pass this to input inside the component>
</custom-input>
Run Code Online (Sandbox Code Playgroud)
web*_*now 32
您不应该将formControlName
属性添加到自定义组件的模板中的输入字段.您应该根据formControlName
最佳实践添加自定义输入元素本身.
您可以在自定义输入组件中使用的controlValueAccessor
界面是,只要自定义输入的模板中的输入字段事件发生更改或模糊,您的自定义输入就会更新值.
它提供了自定义输入的表单控件行为与您为该自定义表单控件提供的UI之间的连接(以更新值或其他需求).
下面是TypeScript中自定义输入组件的代码.
import { Component, Input, forwardRef, AfterViewInit, trigger, state, animate, transition, style, HostListener, OnChanges, ViewEncapsulation, ViewChild, ElementRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormControl } from '@angular/forms';
export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => InputComponent),
multi: true
};
@Component({
selector: 'inv-input',
templateUrl:'./input-text.component.html',
styleUrls: ['./input-text.component.css'],
encapsulation: ViewEncapsulation.None,
providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR],
animations:[trigger(
'visibilityChanged',[
state('true',style({'height':'*','padding-top':'4px'})),
state('false',style({height:'0px','padding-top':'0px'})),
transition('*=>*',animate('200ms'))
]
)]
})
export class InputComponent implements ControlValueAccessor, AfterViewInit, OnChanges {
// Input field type eg:text,password
@Input() type = "text";
// ID attribute for the field and for attribute for the label
@Input() idd = "";
// The field name text . used to set placeholder also if no pH (placeholder) input is given
@Input() text = "";
// placeholder input
@Input() pH:string;
//current form control input. helpful in validating and accessing form control
@Input() c:FormControl = new FormControl();
// set true if we need not show the asterisk in red color
@Input() optional : boolean = false;
//@Input() v:boolean = true; // validation input. if false we will not show error message.
// errors for the form control will be stored in this array
errors:Array<any> = ['This field is required'];
// get reference to the input element
@ViewChild('input') inputRef:ElementRef;
constructor() {
}
ngOnChanges(){
}
//Lifecycle hook. angular.io for more info
ngAfterViewInit(){
// set placeholder default value when no input given to pH property
if(this.pH === undefined){
this.pH = "Enter "+this.text;
}
// RESET the custom input form control UI when the form control is RESET
this.c.valueChanges.subscribe(
() => {
// check condition if the form control is RESET
if (this.c.value == "" || this.c.value == null || this.c.value == undefined) {
this.innerValue = "";
this.inputRef.nativeElement.value = "";
}
}
);
}
//The internal data model for form control value access
private innerValue: any = '';
// event fired when input value is changed . later propagated up to the form control using the custom value accessor interface
onChange(e:Event, value:any){
//set changed value
this.innerValue = value;
// propagate value into form control using control value accessor interface
this.propagateChange(this.innerValue);
//reset errors
this.errors = [];
//setting, resetting error messages into an array (to loop) and adding the validation messages to show below the field area
for (var key in this.c.errors) {
if (this.c.errors.hasOwnProperty(key)) {
if(key === "required"){
this.errors.push("This field is required");
}else{
this.errors.push(this.c.errors[key]);
}
}
}
}
//get accessor
get value(): any {
return this.innerValue;
};
//set accessor including call the onchange callback
set value(v: any) {
if (v !== this.innerValue) {
this.innerValue = v;
}
}
//propagate changes into the custom form control
propagateChange = (_: any) => { }
//From ControlValueAccessor interface
writeValue(value: any) {
this.innerValue = value;
}
//From ControlValueAccessor interface
registerOnChange(fn: any) {
this.propagateChange = fn;
}
//From ControlValueAccessor interface
registerOnTouched(fn: any) {
}
}
Run Code Online (Sandbox Code Playgroud)
下面是自定义输入组件的模板HTML
<div class="fg">
<!--Label text-->
<label [attr.for]="idd">{{text}}<sup *ngIf="!optional">*</sup></label>
<!--Input form control element with on change event listener helpful to propagate changes -->
<input type="{{type}}" #input id="{{idd}}" placeholder="{{pH}}" (blur)="onChange($event, input.value)">
<!--Loop through errors-->
<div style="height:0px;" [@visibilityChanged]="!c.pristine && !c.valid" class="error">
<p *ngFor="let error of errors">{{error}}</p>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
下面是自定义输入组件,可以在fromGroup或单独使用
<inv-input formControlName="title" [c]="newQueryForm.controls.title" [optional]="true" idd="title" placeholder="Type Title to search"
text="Title"></inv-input>
Run Code Online (Sandbox Code Playgroud)
通过这种方式,如果您实现自定义表单控件,则可以轻松应用自定义验证程序指令,并在该表单控件上累积错误以显示错误.
可以模仿相同的样式以上述方式开发自定义选择组件,单选按钮组,复选框,文本区域,文件上载等,并根据表单控件的行为要求进行微小更改.
dar*_*o99 17
Angular 8 和 9:在自定义组件中使用 viewProvider。工作示例:
@Component({
selector: 'app-input',
templateUrl: './input.component.html',
styleUrls: ['./input.component.scss'],
viewProviders: [
{
provide: ControlContainer,
useExisting: FormGroupDirective
}
]
})
Run Code Online (Sandbox Code Playgroud)
现在,当您分配 formControlName 时,您的组件将自身附加到父表单。
<input matInput formControlName="{{name}}">
Run Code Online (Sandbox Code Playgroud)
或者
<input matInput [formControlName]='name'>
Run Code Online (Sandbox Code Playgroud)
这里的主要思想是你必须将FormControl链接到FormGroup,这可以通过将FormGroup传递给每个输入组件来完成......
因此,您的输入模板可能如下所示:
<div [formGroup]="form">
<label *ngIf="label">{{ label }}</label>
<input [formControlName]="inputName" />
<span *ngIf="message">{{ message }}</span>
</div>
Run Code Online (Sandbox Code Playgroud)
其中@Input
的用于输入组件会form
,label
,inputName
和message
.
它会像这样使用:
<form [FormGroup]="yourFormGroup">
<custom-input
[form]="yourFormGroup"
[inputName]="thisFormControlName"
[message]="yourMessage"
[label]="yourLabel">
</custom-input>
</form>
Run Code Online (Sandbox Code Playgroud)
有关自定义表单输入组件的更多信息,我建议您查看Angular的动态表单.此外,如果您想了解有关如何获取@Input
和@Output
工作的更多信息,请查看Angular Docs Here
归档时间: |
|
查看次数: |
32772 次 |
最近记录: |