angular – 通过查询组件的模板来获取FormControl实例
我有一个自定义FormFieldComponent,它封装了表单字段的
HTML和错误显示逻辑:
@Component({ selector: 'field',template: ` <div class="form-group"> <label class="control-label">{{label}}</label> <ng-content></ng-content> <!-- Will display the field --> <!-- Here,put error display logic --> </div> ` }) export class FormFieldComponent { @Input() label: string; // Field label @Input() theControl: FormControl; // Current form control,required to display errors } 在FormFieldComponent中,我需要一个FormControl实例来显示错误. 我的表单看起来像这样: <form [formGroup]="myForm"> ... <field label="Title" [theControl]="myForm.get('title')"> <input type="text" formControlName="title"> </field> ... </form> 但我对上面的代码并不完全满意.如您所见,我在两个位置指定字段的键:在[theControl]输入属性和formControlName指令中. 如果我能写的话,代码会更简洁: <field label="Title"> <input type="text" formControlName="title"> </field> 注意[theControl]输入属性是如何消失的. FieldComponent应该能够获得它包含的FormControl实例,但是如何实现呢? 我已经尝试使用@ContentChildren装饰器来查询FormControl指令的组件模板,但它不起作用: export class FormFieldComponent { @ContentChildren(FormControlDirective) theControl: any; } 另一种选择是将字段的键作为输入传递给FormFieldComponent,然后让组件使用该键: >以编程方式将formControlName指令应用于它包含的字段.
简短的回答:你不能
你不能. (好吧,也许你可以,但它会是hacky!) 答案很长:你不能,但…… FormControl不可注射.指令是可注入的,但是,您必须处理formControlName,ngModel,formControl等,并且它们不能从包装组件访问,但它的子代… 对于你的情况,你可以试试@ContentChildren(FormControlName)theControl:any;因为你的代码中没有暗示FormControlDirective,但你无论如何都无法访问FormControl(属性_control是内部的,所以它会是一个hack)… 因此,您应该坚持从处理FormGroup的组件中管理错误. 但是,如果你想显示一个自定义输入(不会显示错误信息,但能够显示此输入处于错误状态(主机元素将获得ng-valid,ng-invalid类,所以它只是你可以通过实施
这意味着实现此接口的指令/组件可以与ngModel,formControl等一起使用… 例如:< my-component [(ngModel)] =“foo”>< / my-component> 它不是你问题的确切复制品,但是这个实现为我解决了同样的问题: export const INPUT_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR,useExisting: forwardRef(() => InputComponent),multi: true }; @Component({ selector: "field",template: `<!--put anything you want in your template--> <label>{{label}}</label> <input #input (input)="onChange($event.target.value)" (blur)="onTouched()" type="text">`,styles: [],providers: [INPUT_VALUE_ACCESSOR] }) export class InputComponent implements ControlValueAccessor { @ViewChild("input") input: ElementRef; @Input() label:string; onChange = (_: any) => { }; onTouched = () => { }; constructor(private _renderer: Renderer) { } writeValue(value: any): void { const normalizedValue = value == null ? "" : value; this._renderer.setElementProperty(this.input.nativeElement,"value",normalizedValue); } registerOnChange(fn: (_: any) => void): void { this.onChange = fn; } registerOnTouched(fn: () => void): void { this.onTouched = fn; } setDisabledState(isDisabled: boolean): void { this._renderer.setElementProperty(this.input.nativeElement,"disabled",isDisabled); } } 那你就可以: <field label="Title" formControlName="title"></field> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |