簡體   English   中英

Angular 7 Custom mat-checkbox不會使用ControlValueAccessor更新表單有效性

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM