Angular ControlValueAccessor со значением по умолчанию из внутренних причин - PullRequest
1 голос
/ 17 января 2020

У меня есть директива для создания динамических c Входные компоненты для формы на основе шаблона. Значение по умолчанию устанавливается самим компонентом ввода.

Проблема состоит в том, что установка значения по умолчанию приводит к тому, что форма помечается как грязная.

Как можно архивировать установку значения по умолчанию изнутри Директивы, не помечая форму как грязную ?

@Directive({
  selector: '[myFormInputFactory]',
  providers: [
    { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MyFormFactoryDirective), multi: true }
  ]
})
export class MyFormFactoryDirective implements OnChanges, OnDestroy, ControlValueAccessor {
  @Input() myFormInputFactory: DialogItem;

  private componentRef: any;
  private value: any;
  private valueSubscription: Subscription;
  private disabled = false;

  constructor(
    private viewContainerRef: ViewContainerRef,
    private componentFactoryResolver: ComponentFactoryResolver,
    private _renderer: Renderer,
    private _elementRef: ElementRef
  ) { }

  onChange = (_: any) => { };
  onTouched = () => { };

  registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
  registerOnTouched(fn: () => void): void { this.onTouched = fn; }


  ngOnChanges(changes: SimpleChanges) {
    if ('myFormInputFactory' in changes) {
      const config = changes['myFormInputFactory'].currentValue as IConfigItem;

      const factories = Array.from(this.componentFactoryResolver['_factories'].values());
      const comp = factories.find((x: any) => x.selector === config.selector) as ComponentFactory<{}>;
      const componentRef = this.viewContainerRef.createComponent(comp);

      if (this.componentRef) {
        this.componentRef.destroy();
      }
      this.componentRef = componentRef;
      this.valueSubscription = this.componentRef._component.valueChange.subscribe(value => {
        this.value = value;
        this.onChange(this.value);
      });
    }
  }

  ngOnDestroy() {
    if (this.valueSubscription) {
      this.valueSubscription.unsubscribe();
    }
  }

  writeValue(value: string): void {
    if (this.value !== null) {
      this.onChange(this.value);
    }
     if (value !== undefined && value !== null) {
       this.value = value;
    }
  }
}

ОБНОВЛЕНИЕ

Я создал StackBlitz

Ответы [ 2 ]

0 голосов
/ 17 января 2020

Я думаю, проблема в том, что вы звоните this.onChange в writeValue. writeValue используется для уведомления элемента управления о том, что значение было изменено извне, с помощью формы, поэтому вызывать onChange для уведомления формы об изменении не нужно.

0 голосов
/ 17 января 2020

Не могли бы вы создать сообщение StackBlitz для лучшей отладки?

Я думаю, что часть проблемы может заключаться в доступе к входу, а не в самом FormControl. Прямой доступ к самому входу затем вызывает событие onChange и помечает вход как грязный, что, на мой взгляд, может быть проблемой.

Как вы используете директиву? Можно ли сделать следующее?

  1. Создать FormGroup в родительском компоненте
  2. При использовании директивы myFormInputFactory передать соответствующую ссылку FormControl в директиву и присвоить значение для сам элемент управления:

    this.formgroup.setValue ({ключ: значение}, {emitEvent: false})

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...