我正在尝试使用 Angular 8 创建自定义输入组件。我想使用 JSON 元数据动态加载该自定义输入组件。当我渲染组件时,我想使用 Reactive 表单将值绑定到它。父组件将创建表单组,我将相应地设置我的自定义组件 formControlName。
我尝试将 ControlValueAccessor 接口添加到组件并实现了接口方法。但是它们都没有触发。我还为我的组件 NG_VALUE_ACCESSOR 提供了提供程序。
@Component({
selector: "app-text-box",
templateUrl: "./text-box.component.html",
styleUrls: ["./text-box.component.scss"],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextBoxComponent),
multi: true
}
]
})
export class TextBoxComponent implements OnInit, Generic, ControlValueAccessor {
public id: string;
public label: string;
public type: string;
public value: any;
constructor() {}
ngOnInit() {
console.log("inside oninit", this);
}
registerOnChange(fn: any) {
console.log("onchange : ", fn);
}
registerOnTouched(fn: any) {
console.log("registerOnTouche : ", fn);
}
writeValue(value: any) {
console.log("onwrite : ", value);
if (value) {
this.value = value;
}
}
setDisabledState(isDisabled: boolean) {
console.log("ondisable : ", isDisabled);
}
}
文本框模板代码:
<div class="form-group">
<label for="textBox">{{ label }}</label>
<input type="{{ type }}" class="form-control" id="{{ id }}" placeholder="{{ placeholder }}" [value]="value" />
<small id="{{ helpMessageId }}" class="form-text text-muted">{{ helpMessage }}</small>
</div>
指令代码:
@Directive({
selector: "[r-dynamic-form]"
})
export class DynamicFormDirective implements OnInit {
@Input("config") config: any;
constructor(private factory: ComponentFactoryResolver, private ref: ViewContainerRef) {}
ngOnInit() {
const componentFactory = this.factory.resolveComponentFactory(this.config.component);
let component = this.ref.createComponent(componentFactory);
this.setComponentProperties(component);
console.log("directive : ", component.injector);
}
setComponentProperties(component: any) {
Object.keys(this.config.data).forEach(key => {
component.instance[key] = this.config.data[key];
});
component.instance["formControlName"] = this.config.data["id"];
}
}
根组件模板
<form [formGroup]="regForm" (ngSubmit)="onSubmit($event)">
<ng-container *ngFor="let item of dynamicForm" r-dynamic-form [config]="item"></ng-container>
<!-- <app-text-box formControlName="username"></app-text-box>
<app-text-box formControlName="password"></app-text-box> -->
<button>Submit</button>
</form>
根组件.ts 文件
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"]
})
export class AppComponent implements OnInit {
@ViewChildren(TextBoxComponent) textbox: QueryList<TextBoxComponent>;
dynamicForm: any;
regForm: FormGroup;
constructor(private service: AppServiceService, private fb: FormBuilder) {}
ngOnInit() {
this.regForm = this.fb.group({
username: ["test"],
password: [""]
});
this.dynamicForm = this.service.generateCompoenetsByMetaData();
}
onSubmit(e) {
console.log(e, this.regForm.getRawValue(), this.textbox);
}
}
示例 json:我们从服务方法中获得
{ component: TextBoxComponent, data: { type: 'text', placeholder: 'username', label: 'UserName', id: 'username' } },
{ component: TextBoxComponent, data: { type: 'password', placeholder: 'password', label: 'Password', id: 'password' } }
期望执行接口方法。但是没有一个接口方法正在执行/调用。因此没有发生绑定。