[英]Angular 7 Custom mat-checkbox doesn't update form validity with ControlValueAccessor
我已經創建了一個自定義的mat-checkbox組件並實現了ControlValueAccessor接口,以便與傳遞的formControl或ngModel進行通信。
該復選框在更改時更新已分配的formControl,但我的問題是它似乎沒有注冊驗證器函數,無論是模板驅動還是反應方式。
這是我的組成部分:
import {Component, Input, OnInit, Self, ViewEncapsulation} from '@angular/core';
import {ControlValueAccessor, NgControl} from '@angular/forms';
@Component({
selector: 'app-checkbox',
templateUrl: './checkbox.component.html',
styleUrls: ['./checkbox.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class CheckboxComponent implements OnInit, ControlValueAccessor {
@Input() id: string;
@Input('aria-label') ariaLabel: string;
@Input() label: string;
private isChecked = false;
private isDisabled = false;
onChange = (isChecked: boolean) => {};
onTouched = () => {};
constructor(@Self() public controlDir: NgControl) {
// providing component as ControlValueAccessor
controlDir.valueAccessor = this;
}
ngOnInit() {
// Initializing assigned FormControl and providing it's Validator
const control = this.controlDir.control;
control.setValidators(control.validator);
control.updateValueAndValidity();
}
/**
* ControlValueAccessor interface (https://angular.io/api/forms/ControlValueAccessor)
* Registers a callback function that is called when the control's value changes in the UI.
* @param fn callback function
*/
registerOnChange(fn: (value: boolean) => void): void {
this.onChange = fn;
}
/**
* Input change callback that passes the changed string to this.onChange method
*/
valueChanged(value: boolean) {
this.onChange(value);
}
/**
* ControlValueAccessor interface
* Registers a callback function is called by the forms API on initialization to update the form model on blur.
* @param fn callback function
*/
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
/**
* (optional) - ControlValueAccessor interface
* Function that is called by the forms API when the control status changes to or from 'DISABLED'. Depending on the status, it enables or disables the appropriate DOM element.
* @param isDisabled control state
*/
setDisabledState(isDisabled: boolean): void {
this.isDisabled = isDisabled;
}
/**
* ControlValueAccessor interface
* Writes a new value to the element.
* @param value new control value
*/
writeValue(value: boolean): void {
if (value) {
this.isChecked = value;
}
}
}
這是我的模板:
<mat-checkbox color="primary" [checked]="isChecked" [disabled]="isDisabled" [id]="id" [attr.aria-label]="ariaLabel" (change)="valueChanged($event.checked)" (blur)="onTouched()">
{{label}}
</mat-checkbox>
這就是我用模板驅動的方式調用我的組件的方式:
<form class="row border-bottom" #checkboxForm2="ngForm">
<div class="col-12 col-md-4 my-1">
checkboxForm2.value: <br>
{{checkboxForm2.value | json}} <br>
checkboxForm2.valid: {{checkboxForm2.valid}}
</div>
<div class="col-12 col-md-8 my-3">
<app-checkbox [ngModel]="false" name="checkbox3" label="REQUIRED" required></app-checkbox>
</div>
</form>
checkboxForm2.valid
始終保持為true。 如何使所需的驗證器工作?
我設法通過調用一個函數來檢查控件是否附加了Validators.required
並在組件的writeValue
CVA接口方法中設置Validators.requiredTrue
。 這是我的代碼:
export class CheckboxComponent implements DoCheck, ControlValueAccessor {
...
writeValue(value: boolean): void {
this._isChecked = !!value;
this._autoSelected = !!value;
const control = this._controlDir.control;
// Adding Validators.requiredTrue if Validators.required is set on control in order to make it work with template-driven required directive
if (this.hasRequiredValidator(control)) {
control.setValidators([control.validator, Validators.requiredTrue]);
} else {
control.setValidators(control.validator);
}
}
...
/**
* Returns whether checkbox is required
* @param abstractControl control assigned to component
*/
hasRequiredValidator(abstractControl: AbstractControl): boolean {
if (abstractControl.validator) {
const validator = abstractControl.validator({} as AbstractControl);
if (validator && validator.required) {
return true;
}
}
return false;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.