0

我正在尝试使用 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' } }

期望执行接口方法。但是没有一个接口方法正在执行/调用。因此没有发生绑定。

4

0 回答 0