【问题标题】:Changes ngControl.valueAccessor for dynamically changes component为动态更改组件更改 ngControl.valueAccessor
【发布时间】:2020-10-29 12:23:48
【问题描述】:

在我的 Angular 应用程序中,我有一个动态更改输入组件的表单。所有动态组件都实现了 ControlValueAccessor。

如果您在 Input 中输入值并下一个更改组件(单击按钮“将组件更改为数字”),则 ngControl 不会将其引用 valueAccessor 更改为新组件。而且我的新 Input 组件不会改变我的模型。我究竟做错了什么 ? 我在stackblitz 中有一个例子。我有一个示例代码。

我的动态表单组件:

@Component({
  selector: "app-form-control-outlet",
  template: ``,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => FormControlOutletComponent),
      multi: true
    }
  ]
})
export class FormControlOutletComponent implements OnChanges {
  @Input() component = CustomStringInputComponent;

  componentRef: ComponentRef<any>;

  constructor(
    public injector: Injector,
    private container: ViewContainerRef,
    private resolver: ComponentFactoryResolver,
    private viewContainerRef: ViewContainerRef
  ) {}

  public ngOnChanges(changes: SimpleChanges): void {
    const factory = this.resolver.resolveComponentFactory(this.component);

    const componentFactory = this.resolver.resolveComponentFactory(
      this.component
    );

    if (this.container.length > 0) {
      this.container.clear();
    }

    this.componentRef = this.viewContainerRef.createComponent(componentFactory);

    const ngControl = this.injector.get(NgControl);
    ngControl.valueAccessor = this.componentRef.instance;
  }
}

我的动态输入之一

 @Component({
  selector: "app-custom-input",
  template: `
    <input
      [(ngModel)]="value"
      (ngModelChange)="onValueChange($event)"
      (blur)="onInputBlurred()"
    />
  `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomStringInputComponent),
      multi: true
    }
  ]
})
export class CustomStringInputComponent implements ControlValueAccessor {
  public value: string;
  public onChange: (value: string) => void;
  public onTouched: () => void;

  public writeValue(value: string): void {
    this.value = value;
  }

  public registerOnChange(fn: (value: string) => void): void {
    this.onChange = fn;
  }

  public registerOnTouched(fn: () => void): void {
    this.onTouched = fn;
  }

  public onValueChange(value: string): void {
    this.writeValue(value);
    this.onChange(value);
  }

  public onInputBlurred(): void {
    this.onTouched();
  }
}

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    发生这种情况是因为当您更改 valueAccessor 时,Angular 不会再次在该新组件上注册 onChange 和 onTouched 事件。

    您可以尝试的解决方法是手动注册这些事件:

    const ngControl = this.injector.get(NgControl);
    const valueAccessor = ngControl.valueAccessor as any;
    if (valueAccessor && valueAccessor.onChange) {
      this.componentRef.instance.registerOnChange(valueAccessor.onChange);
      this.componentRef.instance.registerOnTouched(valueAccessor.onTouched);
    }
    ngControl.valueAccessor = this.componentRef.instance;
    

    Forked Stackblitz

    【讨论】:

      猜你喜欢
      • 2021-03-31
      • 2017-03-24
      • 1970-01-01
      • 1970-01-01
      • 2018-10-19
      • 2011-01-25
      • 1970-01-01
      • 2011-09-06
      • 2018-10-19
      相关资源
      最近更新 更多