Angular 7自定义垫复选框不会使用ControlValueAccessor更新表单有效性

时间:2019-05-15 18:12:18

标签: angular typescript angular-material angular-components 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始终为真。如何使所需的验证器起作用?

1 个答案:

答案 0 :(得分:0)

我设法通过调用一个函数来检查控件是否已附加[1] "integer" [1] TRUE [1] "integer" [1] TRUE 并在组件的Validators.required的CVA接口方法中设置Validators.requiredTrue来使其工作。这是我的代码:

writeValue