Событие onChange не срабатывает с FormControl и ControlValueAccessor (угловой 6)

Я пытаюсь обернуть ng-select (https://github.com/ng-select/ng-select) с пользовательским компонентом, я использую ControlValueAccessor с реактивной формой,

export class ShNgSelectComponent implements OnInit, OnChanges, 
ControlValueAccessor {
   @Input() shItems: Array<object>;
   @Input() shBindValue: string;
   @Input() shBindLabel: string;
   @Input() shPlaceholder: any;

  @Output() shChange = new EventEmitter<Object>();

  ngOnInit() {  
  }


  writeValue(value: any): void {
    this.shItems = value || '';
  }

  propagateChange(event){
    this.shChange.emit(event);
   }


  registerOnChange(fn) {
    this.propagateChange = fn;
   }

  registerOnTouched() { }
}

вот шаблон для sh-ng-select

<ng-select [items]='shItems' [bindValue]='shBindValue' [placeholder]='shPlaceholder' [bindLabel]='shBindLabel' (change)='propagateChange($event)'></ng-select>

и вот основной компонент, в который я хочу встроить свой пользовательский компонент

<sh-ng-select [shItems]='manufactureList' [shFormGroup]='requestForm' (shChange)='getModels($event)' formControlName="manufactureId" [shPlaceholder]='"اختر الشركة المصنعة"' [shBindValue]='"id"' [shBindLabel]='"name"'></sh-ng-select>

событие shChange срабатывает обычно до того, как я добавляю formControlName, но как только я это делаю, событие не срабатывает, и консоль не выдает никаких ошибок..... почему?


person M. Gamie    schedule 18.09.2018    source источник


Ответы (1)


Для меня, когда вы добавляете formControlName, он связывает все, что нужно для работы, поэтому он вызывает registerOnChange , registerOnTouched, writeValue... так как он вызывает registerOnChange и делает "this.propagateChange = fn" Метод propageChange больше не будет ссылаться на тот, который вы определили:

  propagateChange(event){
    this.shChange.emit(event);
   }

Таким образом, генератор событий shChange больше не вызывается.


Для получения дополнительной информации о том, как заставить компоненты, работающие с [(ngModel)] / formControlName, повторять один и тот же шаблон, здесь вы можете найти простую реализацию, которую вы можете расширить для использования в своем компоненте: https://github.com/xrobert35/asi-ngtools/blob/master/src/components/common/default-control-value-accessor.ts

Простой компонент, использующий его: https://github.com/xrobert35/asi-ngtools/blob/master/src/components/asi-checkbox/asi-checkbox.component.ts

person xrobert35    schedule 18.09.2018
comment
он работал после выполнения вышеуказанной реализации, за исключением того, что выдает ошибку: ERROR TypeError: items.map не является функцией, это связано с тем, что shItems, который передается [items] в ng-select, преобразуется в строку и [items] принимает массив - person M. Gamie; 18.09.2018
comment
Когда formControl инициализируется, он вызовет writeValue со значением по умолчанию. Здесь я думаю, что значение по умолчанию не определено, поэтому this.shItems = value || ''; определит this.shItems как '', вы должны написать: this.shItems = value || []; - person xrobert35; 18.09.2018
comment
это сработало после удаления this.shItems = value || ''; из метода writeValue() - person M. Gamie; 18.09.2018
comment
что вы написали вместо этого? - person xrobert35; 18.09.2018
comment
Я оставил его пустым! - person M. Gamie; 18.09.2018
comment
Если вы оставите его пустым, вы не сможете определить значение по умолчанию из formControl, поэтому вам следует обработать этот случай. Кроме того, вы также должны управлять отключенным setDisabledState(disabled: boolean): void { this.disabled = disabled; } который также можно установить из formControl - person xrobert35; 18.09.2018
comment
Давайте продолжим обсуждение в чате. - person M. Gamie; 18.09.2018