- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想创建一个可以与 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>
组件:
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;
}
用法:
<custom-input label="Title"
formControlName="title" // Pass this to input inside the component>
</custom-input>
最佳答案
您不应将 formControlName
属性添加到自定义组件模板中的输入字段。根据最佳实践,您应该在自定义输入元素本身上添加 formControlName
。
在这里,您可以在自定义输入组件中使用的是 controlValueAccessor
接口(interface),只要您的自定义输入模板中出现输入字段事件,您的自定义输入就会更新值改变或模糊。
它在您的自定义输入的表单控件行为与您为该自定义表单控件提供的 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) {
}
}
下面是自定义输入组件的模板 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>
下面是自定义输入组件,可以在 fromGroup 中使用,也可以单独使用
<inv-input formControlName="title" [c]="newQueryForm.controls.title" [optional]="true" idd="title" placeholder="Type Title to search"
text="Title"></inv-input>
以这种方式,如果您实现自定义表单控件,您可以轻松应用自定义验证器指令并在该表单控件上累积错误以显示您的错误。
可以仿照上面的样式开发自定义select组件,radio button group, checkbox, textarea, fileupload等,根据表单控件的行为需求稍作改动。
关于Angular 2 - 组件内部的 formControlName,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39661430/
我正在尝试来自官方 Angular 响应式(Reactive)表单验证 doc 。我在渲染 formControlName 时遇到问题。它给出了用户名未定义的错误这里有一个错误 Error: Unca
我创建了 form: FormGroup 变量,我在服务的构造函数中使用 FormArray localizationData: FormArray 定义了组: this.form = this.fo
我正在使用响应式控件构建动态表单,我需要能够显示数据而不是在输入控件中使用它。我基本上有一个开关,可以在基于输入和只读(用于打印)之间切换表单。但是,我不能将 label 或 span 与 formC
我想创建一个自定义输入组件并在我的表单中重用它,但我遇到了 formGroup 和 formControlName 的问题。 // Form // CustomInput Component
在括号内使用 formControlName 和不在括号内有什么区别?在动态表单教程中 formcontrolname 被用在方括号内 [formControlName]="dyncontrol.ke
我在 Mat-Autocomplete 上使用 formControlName 时遇到问题。 我不知道为什么,但我的 formControlName 不会发送数据,是我写错了吗? 当我尝试从 HTML
我想创建一个可以与 FormBuilder API 一起使用的自定义输入组件。如何在组件中添加 formControlName? 模板: {{ label }}
新: 所以我可以让它在没有 radio 组或没有正确绑定(bind)的情况下工作。我无法让它与两者一起工作。 这是允许的:
我正在使用 mat-select ,我需要为它设置默认值。它有效,但在向其添加 formControlName 后,不显示其默认值。 我试过 [(ngModel)] 和 [(value)] ,以及“m
在创建模型驱动表单时,我收到一个错误:错误:formControlName 必须与父 formGroup 指令一起使用。您需要添加一个 formGroup 指令并将其传递给现有的 FormGroup
我想通过实现 ControlValueAccessor 创建自定义表单元素地址。 我正在尝试创建一个 AddressComponent,其中有多个输入字段。我想在如下所示的 react 形式中使用此组
我想通过实现 ControlValueAccessor 创建自定义表单元素地址。 我正在尝试创建一个 AddressComponent,其中有多个输入字段。我想在如下所示的 react 形式中使用此组
我正在通过 angularjs2 中的表单生成器制作表单,我想添加表单元素的 formControlName 属性/属性,如下所示: 我该怎么做? 编辑: 我还想将有效性消息放在输入元素旁边,
如何将 formControlName 映射到特定的 formArray 项? 我无法控制服务器数据并尝试创建一个包含电话号码数组的表单。 表单本身在视觉上并没有将手机并排布置,我希望能够像通常使用
我曾经有一个没有任何验证的简单表单,其中 HTML 大致如下所示: [(ngModel)]="todoListService.toDoData.tas
我希望将数字管道添加到 Angular2 中的输入字段。我正在使用模型驱动的表单,我的所有输入都有一个 formControlName 而不是使用数据绑定(bind)。我遇到的问题是 formCont
我正在使用基于模型的表单,我的表单如下所示: Submit 我想写一个 Protractor 规范来测试登录。我喜欢在我的规范中做类似下面的事情: element(by.f
哦,angular2...为什么这么难? {{exposure}} 如果我在输入中使用 formControlName,则值是正确的。 如何获取模板中的曝光值?标签中的空白 最佳答案 The for
作为 Angular documentation说我们可以在表单中使用 formControlName: Hero Detail FormControl in a FormGroup
我正在使用 Angular2 的 ReactiveFormsModule 创建一个包含表单的组件。这是我的代码: foo.component.ts: constructor(fb: FormBuild
我是一名优秀的程序员,十分优秀!