最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to show the 'has-error' class on an invalid field in Angular 2 - Stack Overflow

programmeradmin4浏览0评论

Given:

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

And my custom [fieldValidity] directive:

import { Directive, ElementRef, Input } from 'angular2/core';
import {NgControlName} from 'angular2/mon';
@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');
    }
  }
}

How can I get subscribe to the field.valid && field .pristine values to show the error? (I've marked it with 'TODO' below)

Given:

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

And my custom [fieldValidity] directive:

import { Directive, ElementRef, Input } from 'angular2/core';
import {NgControlName} from 'angular2/mon';
@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');
    }
  }
}

How can I get subscribe to the field.valid && field .pristine values to show the error? (I've marked it with 'TODO' below)

Share Improve this question asked May 8, 2016 at 16:50 williamsandonzwilliamsandonz 16.4k23 gold badges106 silver badges189 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 7

An easy way is to use the data-driven approach with the [ngClass] directive as follows

Template:

<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>

Component:

export class FormComponent implements OnInit {

  private form: FormGroup;
  private description: string;

  constructor(private formBuilder: FormBuilder) { }

  ngOnInit() {
    this.form = this.formBuilder.group({
      description: new FormControl('')
    });
  }
}

You could also implement the ngDoCheck method to check the validity:

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

That said you could implement a wrapping ponent that leverages ngClass directly on the element. Something like that:

@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;
}

You can even go further by directly referencing the control from the ng-content using the @ContentChild decorator:

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

  @ContentChild(NgFormControl) state;

  (...)
}

This way you would be able to define your input this way with ngFormControl (would also work with ngControl):

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

See this article for more details (section "Form ponent for fields"):

  • http://restlet./blog/2016/02/17/implementing-angular2-forms-beyond-basics-part-2/

Make your validation check a validator like shown in https://angular.io/docs/ts/latest/api/mon/FormBuilder-class.html or https://angular.io/docs/ts/latest/cookbook/dynamic-form.html and use a directive like below to set your custom class when Angular sets the ng-invalid class, or just use the ng-invalid class Angular already sets instead of introducing a new one.

@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);
  }
}

You need to add AddClass directive to directives: [AddClass] of the ponent where you want to use it.

发布评论

评论列表(0)

  1. 暂无评论