我正在编写一个旨在简化/同化表单外观和交互方式的组件。代码看起来像这样:
用法示例
http://ourserver/testsys/mynicepgm.aspx
您可以看到...
<my-form-input labelKey = "email" controlName="emailAddress" [form]="userForm">
<input myInput class="form-control" type="email" formControlName="emailAddress" />
</my-form-input>
...
以"emailAddress"
的形式传递给MyFormInputComponent
,并第二次传递给controlName
上的 FormControlName
指令。 <input>
元素。我只想通过一次,这样我的最终用户就不必这样做。
是否有解决这个问题的好方法,或者这只是我应该接受的一个约束(如果是,欢迎解释为什么存在此约束)?代码如下所示。
我尝试了两种方法:
@HostBinding("attr.formControlName")
组件中设置MyInput
批注。我可以通过这种方式在元素上操作名为formcontrolname
的属性,但是它不会触发Angular Forms需要在组中正确注册控件的指令。formControlName
元素提供<input>
并从其余组件中读取该值。这可能有效,但是我必须直接通过ElementRef
,which is not recommended访问DOM。与DOM交互的推荐路线-Renderer
-doesn't seem to expose any ability to read attributes either。my-form-input.component.ts
@Component({
selector: 'my-form-input',
templateUrl: './my-form-input.component.html',
styleUrls: ['./my-form-input.component.scss']
})
export class MyFormInputComponent implements OnInit, AfterContentInit {
@Input()
labelKey: string;
@Input()
controlName: string;
@Input()
form: FormGroup;
@ContentChild(MyInputDirective)
input: MyInputDirective;
ngAfterContentInit(): void {
this.initInput();
}
/**
* Updates the input we project into the template
*/
private initInput() {
this.input.updatePlaceholder(this.labelKey);
// I'd like to somehow edit the FormControlName directive applied to the input here
}
}
my-form-input.component.html
<label>{{ labelKey | translate }}</label>
<ng-content></ng-content>
<my-input-error [control]="form.controls[controlName]" [name]="labelKey | translate" />
my-input.directive.ts
@Directive({
selector: '[myInput]'
})
export class myInputDirective implements OnInit {
private placeholderKey = "";
@HostBinding("placeholder")
private placeholder: string;
updatePlaceholder(placeholderKey: string) {
this.placeholderKey = placeholderKey;
this.placeholder = this.translateService.instant(this.placeholderKey);
}
constructor(private translateService: TranslateService) {
}
}
my-form-error.component.ts
// Not shown since not relevant.
答案 0 :(得分:0)
我仍然不确定确切的解释,但是有些推理暗示了我可能会迷路的地方。
我假设我的组件拥有它要投影的元素,但实际上我认为这是不正确的。您可以在模板中设置属性/指令。这意味着您最好将想要拥有/控制的所有元素都包含在模板中,而不是仅对其进行投影。
在这种情况下,这将导致您为特定的表单控件(例如<input>
,<textarea>
等)制作单独的组件。这就是我最后要做的。无论如何,从设计端点来看这是更好的方法—永远不可能发生一个用于包装所有可能的表单控件的组件。像我在问题中那样,设计一个复制某些属性的表单控件,或者创建特定的组件。或两者兼有(只需将最常用的表单控件放入组件中,将一次性的问题包装在投影组件中即可)。
以下一些博客帮助我找到了自己的路: