【问题标题】:How to show the 'has-error' class on an invalid field in Angular 2如何在 Angular 2 中的无效字段上显示“有错误”类
【发布时间】:2017-02-28 20:41:30
【问题描述】:

给定:

<div class="form-group" [fieldValidity]="email">
  <label for="email" class="sr-only">Email</label>
  <input [(ngModel)]="model.email" ngControl="email" required>
</div>

还有我的自定义 [fieldValidity] 指令:

import { Directive, ElementRef, Input } from 'angular2/core';
import {NgControlName} from 'angular2/common';
@Directive({
  selector: '[fieldValidity]'
})
export class FieldValidityDirective {
  private el: HTMLElement;
  @Input('fieldValidity') field: NgControlName;
  constructor(el: ElementRef) { 
    this.el = el.nativeElement;
  }
  private _onValidityChange(value: string) {
    //TODO test field.valid || field.pristine
    if (?) { 
      this.el.classList.remove('has-error');
    } else {
      this.el.classList.add('has-error');
    }
  }
}

如何订阅 field.valid && field .pristine 值以显示错误? (我在下面用“TODO”标记了它)

【问题讨论】:

    标签: javascript angular


    【解决方案1】:

    一种简单的方法是使用带有 [ngClass] 指令的数据驱动方法,如下所示

    模板:

    <form [formGroup]="form" (ngSubmit)="onSubmit()">
        <div class="form-group">
            <div [ngClass]="{'has-error': form.controls['description'].invalid}">
                <input type="text" formControlName="description" class="form-control" required [(ngModel)]="description">
            </div>
        </div>
        <button type="submit" class="btn btn-success">Submit</button>
    </form>
    

    组件:

    export class FormComponent implements OnInit {
    
      private form: FormGroup;
      private description: string;
    
      constructor(private formBuilder: FormBuilder) { }
    
      ngOnInit() {
        this.form = this.formBuilder.group({
          description: new FormControl('')
        });
      }
    }
    

    【讨论】:

      【解决方案2】:

      您还可以实现ngDoCheck 方法来检查有效性:

      ngDoCheck(value: string) {
        if (field.valid || field.pristine) { 
          this.el.classList.remove('has-error');
        } else {
          this.el.classList.add('has-error');
        }
      }
      

      也就是说,您可以实现一个包装组件,该组件直接在元素上利用ngClass。类似的东西:

      @Component({
        selector: 'field',
        template: `
          <div class="form-group form-group-sm" [ngClass]="{'has-error':state && !state.valid}">
            <label for="for" class="col-sm-3 control-label">{{label}}</label>
            <div class="col-sm-8">
              <!-- Input, textarea or select -->
              <ng-content></ng-content>
              <span *ngIf="state && !state.valid" class="help-block text-danger">
                <span *ngIf="state.errors.required">The field is required</span>
              </span>
          </div>
        </div>
      `
      })
      export class FormFieldComponent {
        @Input()
        label: string;
      
        @Input()
        state: Control;
      }
      

      您甚至可以通过使用 @ContentChild 装饰器直接引用来自 ng-content 的控件来更进一步:

      @Component({
        (...)
      })
      export class FormFieldComponent {
        @Input()
        label: string;
      
        @ContentChild(NgFormControl) state;
      
        (...)
      }
      

      这样您就可以使用ngFormControl 定义您的输入(也可以使用ngControl):

      <form [ngFormModel]="companyForm">
        <field label="Name">
          <input [ngFormControl]="companyForm.controls.name" 
                 [(ngModel)]="company.name"/>
        </field>
      </form>
      

      有关详细信息,请参阅本文(“字段的表单组件”部分):

      【讨论】:

      • 已经实施了ngDoCheck解决方案!如果有人对如何调用 ngDoCheck() 感到困惑。当指令的输入发生变化时,Angular 使用后台魔法自动调用 ngDoCheck。所以只要你使用@input注解就可以了。
      【解决方案3】:

      使您的验证检查像https://angular.io/docs/ts/latest/api/common/FormBuilder-class.htmlhttps://angular.io/docs/ts/latest/cookbook/dynamic-form.html 中所示的验证器,并在Angular 设置ng-invalid 类时使用如下指令来设置您的自定义类,或者只使用Angular 已经设置的ng-invalid 类而不是引入一个新的。

      @Directive({
        selector: 'input'
      })
      export class AddClass {
        @HostBinding('class.has-error')
        hasError:boolean = false;
      
        @Input('class') classes;
        ngOnChanges() {
          this.hasError = classes.split(' ').indexOf('ng-invalid') >= 0);
        }
      }
      

      您需要将AddClass 指令添加到您要使用它的组件的directives: [AddClass]

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-09-12
        • 2014-06-29
        • 2017-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多