Я пытался создать пользовательский компонент ввода, используя 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);
}
}
Шаблон TextBox Код:
<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>
Корневой файл component.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' } }
Ожидается выполнение методов интерфейса.Но ни один из методов интерфейса не выполняется / не вызывается.Поэтому никакой привязки не происходит.