PKD
PKD

Reputation: 707

How to get Angular to show the correct validation message

In my angular page, I have a form:

<div class="row-fluid">
    <div class="control-group" ng-class="{error:form.startDate.$invalid && form.startDate.$dirty && error:form.endDate.$invalid && form.endDate.$dirty}">
        <div class="row-fluid">
            <div class="span4">
                <label><b>Start Date</b> (mm/dd/yyyy)</label>
                <input type="date" 
                        id="startDate"
                        name="startDate"
                        max="{{maxDate}}"
                        min="{{minDate}}"
                        ng-pattern="/^((\d{4})-(\d{2})-(\d{2})|(\d{2})\/(\d{2})\/(\d{4}))$/"
                        ng-model="startDate"
                        required />
            </div>
            <div class="span4">
                <label><b>End Date</b> (mm/dd/yyyy)</label>
                <input type="date" 
                        id="endDate"
                        name="endDate"
                        max="{{maxDate}}"
                        min="{{minDate}}"
                        ng-pattern="/^((\d{4})-(\d{2})-(\d{2})|(\d{2})\/(\d{2})\/(\d{4}))$/"
                        ng-model="endDate"
                        required />
            </div>
        </div>
        <div class="row-fluid">
            <div class="span4">
                <span ng-show="form.startDate.$dirty">
                    <span ng-show="form.startDate.$error.required" class="help-inline">Start Date is required</span>
                    <span ng-show="form.startDate.$error.pattern" class="help-inline">Invalid start date</span>
                    <span ng-show="form.startDate.$error.max" class="help-inline">Start Date exceeds maximum</span>
                </span>
            </div>
            <div class="span4">
                <span ng-show="form.endDate.$dirty">
                    <span ng-show="form.endDate.$error.required" class="help-inline">End Date is required</span>
                    <span ng-show="form.endDate.$error.pattern" class="help-inline">Invalid end date</span>
                    <span ng-show="form.endDate.$error.max" class="help-inline">End Date exceeds maximum</span>
                </span>
            </div>
        </div>
        <input type="button" value="Load Report" ng-click="getLeads()" class="btn btn-primary" />
    </div>
</div>

The fields work as they should, but the validation does not. If I enter '02/30/2015' in either date field, it shows the required message instead of the invalid message.

So, the question is: How can I get the angular $dirty to validate the correct issue: the fields aren't empty, so "required" isn't valid. The date is bad, and should fire off the invalid message.

enter image description here enter image description here

Upvotes: 1

Views: 2199

Answers (1)

Mason Mize
Mason Mize

Reputation: 211

Which version of Angular are you using, if you are using 1.3+ then you can use ng-messages for validation. https://code.angularjs.org/1.3.15/docs/api/ngMessages/directive/ngMessages

The issue you are running into is that both Required and invalid Pattern errors are throw and it is valid to be thrown. Because the value cannot be parsed it is NULL within the ng view model. What ngMessages does under the hood is interrogate the $error object and determine the true error. If you cannot use Angular 1.3 at this time, you could make your own directive to do something similar. Would be a better option than doing something such as ng-show="$error.required && !$error.pattern", while that small expression solves your current case, you will run into more validation cases that would require special long expressions, which is why ngMessages was created.

Here is a Plunker that shows basic usage of ngMessages with your code http://plnkr.co/edit/KaCiJPYaxqzhkSJNskc9?p=preview

<div class="row-fluid">
    <div class="control-group" ng-class="{error:form.startDate.$invalid && form.startDate.$dirty && error:form.endDate.$invalid && form.endDate.$dirty}">
        <div class="row-fluid">
            <div class="span4">
                <label><b>Start Date</b> (mm/dd/yyyy)</label>
                <input type="date" 
                        id="startDate"
                        name="startDate"
                        max="{{maxDate}}"
                        min="{{minDate}}"
                        ng-pattern="/^((\d{4})-(\d{2})-(\d{2})|(\d{2})\/(\d{2})\/(\d{4}))$/"
                        ng-model="startDate"
                        required />
            </div>
            <div class="span4">
                <label><b>End Date</b> (mm/dd/yyyy)</label>
                <input type="date" 
                        id="endDate"
                        name="endDate"
                        max="{{maxDate}}"
                        min="{{minDate}}"
                        ng-pattern="/^((\d{4})-(\d{2})-(\d{2})|(\d{2})\/(\d{2})\/(\d{4}))$/"
                        ng-model="endDate"
                        required />
            </div>
        </div>
        <div class="row-fluid">
            <div class="span4">
                <span ng-messages="form.startDate.$error" ng-if="form.startDate.$dirty">
                    <span ng-message="required">Start Date is required</span>
                    <span ng-message="pattern">Invalid start date</span>
                    <span ng-message="max">Start Date exceeds maximum</span>
                </span>
            </div>
            <div class="span4">
                <span ng-messages="form.endDate.$error" ng-if="form.startDate.$dirty">
                    <span ng-message="required">End Date is required</span>
                    <span ng-message="pattern">Invalid end date</span>
                    <span ng-message="max">End Date exceeds maximum</span>
                </span>
            </div>
        </div>
        <input type="button" value="Load Report" ng-click="getLeads()" class="btn btn-primary" />
    </div>
</div>

Upvotes: 1

Related Questions