Итак, я просто занялся своим делом в Gitter, когда наткнулся на что-то интересное.Взгляните на эту демонстрацию Stackblitz .
Используется пользовательская директива, которая заставляет настраиваемый компонент-флажок работать с ngModel
/ formControl
и т. Д.
Что я не понимаю, так это как события устанавливаются для host
в работе NgCheckboxControlDirective
.Так как хост здесь является селектором для компонента-флажка, а не для самого входа флажка, он не должен вызывать любое событие change
или blur
, но это так.
Если вы установите флажокв демоверсии, связанной сверху, вы увидите, что choosen
изменяется между true
и false
.
Почему?Почему нажатие на флажок вызывает здесь событие change
, которое затем обновляет состояние choosen
?
Директива, которая реализует ControlValueAccessor
:
import { Directive, Renderer2, ElementRef } from '@angular/core';
import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms';
@Directive({
selector: '[ngCheckboxControl]',
host: {'(change)': 'onChange($event.target.checked)', '(blur)': 'onTouched()'},
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: NgCheckboxControlDirective,
multi: true
}
]
})
export class NgCheckboxControlDirective implements ControlValueAccessor {
onChange = (_: any) => {};
onTouched = () => {};
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
writeValue(value: any): void {
this._renderer.setProperty(this._elementRef.nativeElement.firstElementChild, 'checked', value);
}
registerOnChange(fn: (_: any) => {}): void { this.onChange = fn; }
registerOnTouched(fn: () => {}): void { this.onTouched = fn; }
setDisabledState(isDisabled: boolean): void {
this._renderer.setProperty(this._elementRef.nativeElement.firstElementChild, 'disabled', isDisabled);
}
}
Флажок:
import { Component, ElementRef } from '@angular/core';
import { NgControl } from '@angular/forms';
@Component({
selector: 'checkbox-layout',
template: `
My checkbox: <input type="checkbox" />
`,
})
export class CkeckboxLayoutComponent {
constructor(
private ngControl: NgControl,
private elementRef: ElementRef
) {
console.log('... elementRef:', elementRef);
console.log('... ngControl:', ngControl);
}
}
Тогда вы будете использовать это так:
<checkbox-layout formControlName="choosen" ngCheckboxControl></checkbox-layout>