首页 文章

Angular Material和嵌套mat-form-field的CSS问题:错误状态的内部mat-form-field导致父级看起来处于错误状态

提问于
浏览
2

我正在尝试处理一个大表单,为每个部分创建一个自定义组件,在每个自定义组件中放置所有逻辑和自定义验证 . 基本上,每个部分都是子表单,每个部分都有助于大表单的验证过程 .

我也使用Angular Material并且我的自定义组件是custom form field control实现 MatFormField<T> 接口,这样,我将能够使用漂亮的外观来显示整个组件的错误和提示 .

出于这个原因,我将自定义组件包装在 <mat-form-field> 中,甚至自定义组件模板中子表单的字段也包含在_125761中 .

但是这个解决方案和Angular Material有问题 . 如果子表单中的字段无效,则会正确显示自定义组件的 <mat-error> ,甚至会显示内部表单字段的 <mat-error> . 问题是所有其他领域都变成了红色,就好像它们是无效的,但它们实际上并非如此!

这是一个例子:https://stackblitz.com/edit/angular-2h2fql?embed=1&file=src/app/app.component.ts

每个字段都是必需的,只需尝试清除其中一个字段或添加一个新行,甚至所有其他字段都将变为红色 .

我认为这只是CSS的东西,因为当 <mat-form-field> 无效时, <mat-error> 消息类显示 and _ mat-form-field-invalid 类应用于主机元素 <mat-form-field> ,它将红色无效字段变为红色 .

我的问题是:有人知道是否可以手动显示 <mat-error> 或将自定义表单控件设置为错误状态而不将类 .mat-form-field-invalid 应用于主机元素?

根据我的理解,该类绑定到错误状态,如您在此处所见

https://github.com/angular/material2/blob/master/src/lib/form-field/form-field.ts#L120

但我找不到一个优雅的解决方案来克服这个问题 .

我试图应用ShadowDOM视图封装,但它不能正常工作 .

我可以简单地将我的自定义表单控件放在 <mat-form-field> 中,它将正常工作并且 <mat-error> 将显示出来,但不会以材料设计方式显示 .

我错了还是一些Angular Material问题?

希望我的解释明确谢谢

1 回答

  • 0

    我想你可能会对 mat-form-field 的预期目的感到困惑...重要的是要注意奇点, mat-form-fieldmat-form-fields

    在本文档中,“表单字段”是指包装组件<mat-form-field>,“表单字段控件”是指<mat-form-field>包装的组件(例如输入,textarea,select等)

    https://material.angular.io/components/form-field/overview


    尽管该描述可以解释...表单字段包装器的设计旨在是1:1 ...意味着1个包装器,1个控件 .

    • 审查form-field的所有stackblitz示例,您将看到这个1:1标准 .

    https://material.angular.io/components/form-field/examples

    通过将多个 mat-form-fields 包装在父 mat-form-field 中,你实际上将它们全部变成了一个大的 mat-form-field ,它将所有控件视为 errorState 样式方面的一个控件...如果一个无效,它们都是无效的,因为它是一个巨大的 form-field .


    people-list.component.html 中应用以下表单字段包装器,您将看到问题在 OUTSIDE MAT FORM FIELD 示例中被复制 .

    <div [formGroup]="form">
      <mat-form-field>
        <div formArrayName="rows" *ngFor="let p of rows.controls; let i=index">
            <div [formGroupName]="i" fxLayout="row" fxLayoutAlign="space-around center">
    
                <mat-form-field hintLabel="row number {{ i }}" class="full-width">
                    <input matInput type="text" formControlName="name"/>
                    <mat-hint align="end">Valid: {{ p.get('name').valid }}</mat-hint>
                    <mat-error *ngIf="p.get('name').hasError('required')">required</mat-error>
                </mat-form-field>
    
                <mat-form-field class="full-width">
                    <mat-select placeholder="Select state" formControlName="state">
                        <mat-option *ngFor="let state of stateList" [value]="state.abbreviation">
                            {{state.name}}
                        </mat-option>
                    </mat-select>
                    <mat-hint align="end">Valid: {{ p.get('state').valid }}</mat-hint>
                    <mat-error *ngIf="p.get('state').hasError('required')">required</mat-error>
                </mat-form-field>
    
                <button class="glyphicon glyphicon-remove pull-right" *ngIf="rows.length > 0"
                      (click)="removeStep(i)">Remove</button>
                <br>
            </div>
        </div>
        <br>
        <button [disabled]="!rows.valid"
                (click)="addStep()"
                type="button"
                color="primary"
                *ngIf="rows.length < maxlength">
            <span translate>ADD</span>
        </button>
        </mat-form-field>
    </div>
    

    您可能希望使用下面的内容探索在错误时复制表单字段样式 .

    app.component.scss 中创建 mat-form-field-underline

    .matFormFieldUnderline{
      bottom: 1.25em;
      background-color: rgba(0,0,0,.42);
      height: 1px;
      margin-top:5px;
    }
    

    然后在HTML中使用它并复制 mat-form-field 样式

    <h2>OUTSIDE MAT FORM FIELD</h2>
                <app-state-selector
                            name="people2"
                            [ngModel]="peopleList2"
                            #peopleRef2="ngModel"
                            required
                            maxlength=5
                    ></app-state-selector>
                    <div class="matFormFieldUnderline" [style.background-color]="peopleRef2.errors ? 'red' : null"></div>
                    <div fxLayout>
                      <div fxFlex="70">
                       <mat-hint *ngIf="!peopleRef2.errors?.rows">Valid component: {{ peopleRef2.valid }}</mat-hint>
                       <mat-error *ngIf="peopleRef2.errors?.rows">Valid component: {{ peopleRef2.valid }}</mat-error>
                      </div>
                      <div fxFlex="30" fxLayoutAlign="end"> 
                        <mat-hint>{{peopleRef2.value?.length || 0}} rows</mat-hint>
                      </div>
                    </div>  
                    <mat-error *ngIf="peopleRef2.errors?.required">required</mat-error>
                    <mat-error *ngIf="peopleRef2.errors?.maxlength">max 5 rows</mat-error>
    

相关问题