2017-02-10 31 views
9

在AngularJS中有一个名为ng-messages的表单指令,它帮助我们使它不会同时显示所有表单错误。例如,如果输入有3个错误:required,minlength,maxlength。然后只需要显示,在需要有效后,最小长度显示。如果没有ng消息,我们需要做一些非常复杂和难看的逻辑,以便只显示必要的而不是其他的逻辑,同时也考虑到只有当表单控件也是脏/被触摸且无效时才会显示错误。AngularJS中如何解决相同的问题,即ng-messages在AngularJS中解决?

在AngularJS,这将是这样的:

<div ng-messages="form.username.$error" ng-if="form.username.$touched || form.username.$dirty"> 
    <div ng-message="required">Please enter a username.</div> 
    <div ng-message="minlength">Username must be at least 3 characters.</div> 
    <div ng-message="maxlength">Username can't exceed 30 characters.</div> 
</div> 

,我们怎样才能优雅的方式做到这一点的角?

回答

11

您可以制作自己的组件。下面我提供一个例子(没有编译或运行它,但它应该给你足够的信息去实现)。只有在触摸,肮脏等情况下才显示消息的逻辑可以轻松添加到此处。

使用

<validation-messages [for]="control"> 
    <validation-message name="required">This field is required</validation-message> 
</validation-messages> 

实施

import { Component, OnInit, ContentChildren, QueryList, Input, OnDestroy } from '@angular/core'; 
import { FormControl } from '@angular/forms'; 
import { Subscription } from 'rxjs'; 

@Component({ 
    selector: 'validation-messages', 
    template: '<ng-content></ng-content>' 
}) 
export class ValidationMessagesComponent implements OnInit, OnDestroy { 
    @Input() for: FormControl; 
    @ContentChildren(ValidationMessageComponent) messageComponents: QueryList<ValidationMessageComponent>; 

    private statusChangesSubscription: Subscription; 

    ngOnInit() { 
    this.statusChangesSubscription = this.for.statusChanges.subscribe(x => { 
     this.messageComponents.forEach(messageComponent => messageComponent.show = false); 

     if (this.for.status === 'INVALID') { 
     let firstErrorMessageComponent = this.messageComponents.find(messageComponent => { 
      return messageComponent.showsErrorIncludedIn(Object.keys(this.for.errors)); 
     }); 

     firstErrorMessageComponent.show = true; 
     } 
    }); 
    } 

    ngOnDestroy() { 
    this.statusChangesSubscription.unsubscribe(); 
    } 
} 


@Component({ 
    selector: 'validation-message', 
    template: '<div *ngIf="show"><ng-content></ng-content></div>' 
}) 
export class ValidationMessageComponent { 
    @Input() name: string; 
    show: boolean = false; 

    showsErrorIncludedIn(errors: string[]): boolean { 
    return errors.some(error => error === this.name); 
    } 
} 
+0

什么是'[供] = “控制”',其中'control'从何而来? – Felix

+0

'control'是你想要在'ValidationMessagesComponent'中显示验证的'FormControl'。当使用[反应形式](https://angular.io/guide/reactive-forms)时,您可以自己创建这些实例。当使用[template-driven forms](https://angular.io/guide/forms)时,Angular本身会生成这些实例。我的解决方案对反应形式最好/最简单。 –

+0

干得不错。稍微调整一下,对我来说完美无缺。 :) –