【问题标题】:Validation on Custom Angular Material Form Field自定义角度材料表单字段的验证
【发布时间】:2019-03-14 14:48:36
【问题描述】:

我正在尝试使用 ngx-color-picker 和 Angular Materials FormField 为颜色选择器制作包装器组件。我将其配置为required,但它的轮廓不会像其他表单字段一样在无效时变为红色...如何在我的自定义表单字段上实现此行为?

color-picker.component.ts

import { Component, Input, forwardRef } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'

// inspiration:
// https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html

export const requiredValidator = (c: FormControl): ValidationErrors | null => {
    return
    c.value === '' ||
    c.value === null ||
    c.value === undefined ||
    c.value.length === 0
        ? {
              required: {
                  valid: false,
              },
          }
        : null
}

@Component({
    selector: 'nda-color-picker',
    templateUrl: './color-picker.component.html',
    styleUrls: ['./color-picker.component.scss'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => ColorPickerComponent),
            multi: true,
        },
    ],
})
export class ColorPickerComponent implements ControlValueAccessor, Validator {
    @Input() label: string
    _color: string

    get color() {
        return this._color
    }
    set color(value: string) {
        this._color = value
        this.propagateChange(this._color)
    }

    constructor() {}

    writeValue(value: any) {
        if (value !== undefined) {
            this.color = value
        }
    }

    propagateChange = (_: any) => {}

    registerOnChange(fn) {
        this.propagateChange = fn
    }

    registerOnTouched() {}

    validate(control: AbstractControl): ValidationErrors | null {
        return requiredValidator(control as FormControl)
    }
}

color-picker.component.html

<mat-form-field appearance="outline" [floatLabel]="'always'">
    <mat-label>{{ label }}</mat-label>
    <input
        matTooltip="{{ color }}"
        cpOKButton="true"
        cpCancelButton="true"
        [required]="required"
        matInput
        [ngStyle]="{ color: color, background: color }"
        [colorPicker]="color"
        (colorPickerChange)="color = $event"
    />
</mat-form-field>

form-component.html

<form
    [formGroup]="transportForm"
    autocomplete="off"
    (ngSubmit)="handleSubmit()"
>A
    <div mat-dialog-content>
        <div fxLayout="row wrap" fxLayoutGap="1rem">
            <mat-form-field appearance="outline">
                <mat-label>Icon</mat-label>
                <input
                    matInput
                    placeholder="Icon"
                    formControlName="icon"
                    required
                />
            </mat-form-field>
            <nda-color-picker
                label="Badge Color Code"
                formControlName="badgeColorCode"
                required
            ></nda-color-picker>
            <nda-color-picker
                label="Text Color Code"
                formControlName="textColorCode"
                required
            ></nda-color-picker>
            <mat-form-field appearance="outline">
                <mat-label>Badge Type</mat-label>
                <input
                    matInput
                    placeholder="Badge Type"
                    formControlName="badgeType"
                />
            </mat-form-field>
        </div>
    </div>

    <!-- dialog actions -->
    <div mat-dialog-actions fxLayout="row" fxLayoutAlign="space-between center">
        <div>
            <button
                type="button"
                *ngIf="data && data.code"
                color="warn"
                mat-flat-button
                (click)="handleDelete()"
            >
                DELETE
            </button>
        </div>
        <div class="btn-container">
            <button type="reset" mat-stroked-button (click)="handleCancel()">
                CANCEL
            </button>
            <button
                mat-flat-button
                color="accent"
                [disabled]="transportForm.pristine"
            >
                SAVE
            </button>
        </div>
        <div
            *ngIf="!transportForm.valid"
            class="mat-small dialog-error-message"
        >
            * Fill out all required fields
        </div>
    </div>
</form>

----- 更新 ------

我用验证器函数和实现验证器接口的类更新了color-picker.component。验证器函数实际上被调用并按预期工作。但是表单域并没有像通常的反应式表单域那样被标记为无效(css 类.ng-invalid)。

【问题讨论】:

标签: angular angular-material


【解决方案1】:

您可以使用ReactiveFormsModule自定义类来设置不同状态的样式:

.ng-invalid {
  border: 1px solid red;
}

您可以在angular.io...css-classes 中找到有关ReactiveFormsModule css 类的更多文档。

【讨论】:

  • .ng-invalid 没有像所有其他输入一样添加到&lt;nda-color-picker&gt;。所以问题一定是,&lt;nda-color-picker&gt; 根本没有经过验证。
  • 我使用了这个例子 alligator.io/angular/custom-form-control 并添加了验证来制作这个 stackblitz.com/edit/stackoverflow-55165510 。它正在工作。
  • ibenjelloun,你的代码有bug,看我的回答
  • 抱歉,您说的是 alligator.io 的代码,它没有为答案提供额外的价值。 @olefrank 如果您仍然坚持这一点,请针对您的问题进行一次堆栈闪电战,我会在有时间的时候看看。
【解决方案2】:

ibenjelloun,您的代码中存在错误。如果 ratting 等于 0 则替换您的函数 get value() 以返回 null 否则如果选择开始并取消选择不会给您错误

get value(): number {
    let ratting= this.stars.reduce((total, starred) => {
      return total + (starred ? 1 : 0);
    }, 0);
    return ratting?ratting:null;
  }

Olefrank 如果您希望控制是谁给出错误添加提供程序并创建函数验证,请参阅the ibenjelloun forked stackblitz

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 2021-03-15
    • 1970-01-01
    • 2019-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多