Почему мой пользовательский флажок неправильно отображает значение изменения, если я установил тип после представления init? - PullRequest
0 голосов
/ 24 мая 2019

Я пишу некоторые оболочки для обычных элементов управления формой в моем угловом приложении, написав компоненты / директивы, которые имеют селекторы, такие как 'input [custom-input]'.Благодаря этому я могу настроить публичные методы, которые впоследствии можно будет использовать при проецировании контента.

Мой HTML-код выглядит как

<a-component-that-handles-animating-placeholder-etc>
    <input custom-checkbox formControlName="field"/>
</<a-component-that-handles-animating-placeholder-etc>

Преимущество в том, что вход доступен напрямуюк любому компоненту, который может захотеть его использовать, тогда как если бы я написал оболочку, мне пришлось бы реализовать конвейер для каждой функции, например отключенной, например

<custom-input [disabled]="isDisabled"]></custom-input>

Еще одно преимущество заключается в том, что мне не нужно реализовывать новыесредства доступа к пользовательским значениям элементов управления для связывания formcontrolName и осознания фреймворка, когда в действительности реализация пользовательского ввода будет заключаться в том, чтобы просто использовать внутренний ввод, что для каждого элемента управления добавляет много сложности проекту.

Проблема заключается в том, что элемент управления реактивной формы не обновляется с правильным значением, когда флажок установлен и снят.В моем пользовательском компоненте с этим селектором input[custom-checkbox] я делаю эту логику:

  ngAfterViewInit(): void {
    this.renderer.setAttribute(this.el.nativeElement, 'type', 'checkbox');
  }

Это потому, что я не хочу, чтобы потребители указывали, что этот элемент является флажком дважды, например:

<input type="checkbox" custom-checkbox/>

Но по какой-то причине установка типа после рендера прерывает событие, которое обновило элемент управления формы.Я понятия не имею, почему.

РЕДАКТИРОВАТЬ: я раздвоил один из стековых бликов и повторил мою проблему.https://stackblitz.com/edit/angular-dzqp4k

Ответы [ 4 ]

1 голос
/ 28 мая 2019

После вашего блица (и моего) я вспомнил, что входы уже управляются угловыми формами.Вы можете контролировать их через NgControl.

Вот результат

export class InputSelectorDirective {

  @HostBinding('attr.type') inputType: string = "checkbox";

  ngControl: NgControl;

  constructor(
    private R: Renderer2,
    private elRef: ElementRef<HTMLInputElement>,
    private injector: Injector
  ) {
    this.ngControl = injector.get(NgControl);

  }

  ngOnInit() {
    // this.inputType = "checkbox";
    this.ngControl.control.valueChanges
      .subscribe(value => this.ngControl.control.setValue(this.elRef.nativeElement.checked, { emitEvent: false }));
  }
}
0 голосов
/ 29 мая 2019

Ответ, по-видимому, заключается в том, что платформа Angular объявляет, как обращаться с элементами управления формой до запуска привязки хоста, что означает, что для флажков слушатель для его значения уже настроен так, чтобы указывать на input.value, а затем изменяет входные данные.type не меняет слушателя.

Из того, что я пробовал, я думаю, что нет реального решения, вы просто должны убедиться, что элемент управления имеет тип для вашей директивы / компонента ks-checkbox.Вы можете сделать это, используя свойство parentElement, если вы DI elementRef.

0 голосов
/ 27 мая 2019

Вам не нужно устанавливать эти атрибуты вручную при использовании реактивных форм. Вам просто нужно добавить директиву formControl, а все остальное она сделает за вас!

Фрагмент из Angular checkbox_value_accessor исходный код:

/**
* Sets the "checked" property on the input element.
*
* @param value The checked value
*/
writeValue(value: any): void {
this._renderer.setProperty(this._elementRef.nativeElement, 'checked', value);
}

И Stackblitz demo , чтобы увидеть его в действии

0 голосов
/ 27 мая 2019

Ты даже не пойдешь через эту боль.

Просто используйте HostBinding для привязки к attr.type, а при инициализации установите для него флажок.

Демонстрация Stackblitz

export class InputSelectorDirective {

  @HostBinding('attr.type') inputType: string;

  constructor(
    private R: Renderer2,
    private elRef: ElementRef<HTMLInputElement>
  ) { }

  ngOnInit() {
    this.inputType = "checkbox";
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...