10

Is there a way to validate a field in angular without using a directive? For example: I want to make following validation on an input field.

  • If field is empty we should show "Field must contain a value" message.
  • if field contains alpha Numeric characters we should show "Field can contain only digits".
  • An EVEN number - message to the user "Value must be an even number".

I want to make following validation in a call to JavaScript function.

I googled around and saw that there is a way to use ng-valid and $error , however I was not managed to make it work.

Code below is according to one of the answers I got:

<div ng-app>
<form name='theForm' novalidate>
    <input type='text' name='theText' ng-model='theText' ng-pattern='/^[0-9]+$/'/>
    <span ng-show='theForm.theText.$error.pattern'>Field can contain only digits</span>
    <span ng-show='theText.length<1'>Field must contain a value</span>
    <span ng-show='theText%2!=0&&document.getElementsByName("theText").value!=""&&!theForm.theText.$error.pattern&&!theForm.theText.$pristine'>Value must be an even number</span>
    <br/><input type='submit' value='Submit' />
</form>

I want to take what inside the last [span] and put inside a JavaScript function in order to make it more generic and eventually change only JS and not the HTML when conditions are changing

Can someone please advise? a working example would be great.

Oliver Watkins
  • 12,575
  • 33
  • 119
  • 225
Scription
  • 646
  • 3
  • 12
  • 21
  • If you wanna do all of these validations in a javascript function, why not go the angular way and create a custom validation directive? – Shay Friedman Aug 08 '13 at 12:39
  • Why do you want to use a Javascript function ? Angular can do it while watching the models like here : http://jsfiddle.net/DotDotDot/6UJZk/1/ , using another function wouldn't be as efficient I think – DotDotDot Aug 08 '13 at 12:44

4 Answers4

23

I'm surprised no one has mentioned ui-validate

$scope.isOdd = function($value){
  return $value % 2;
}
...
<form name="myform">
  <input ng-model="myVal" name="value" required
    ng-pattern="/^[0-9]*$/" ui-validate=" 'isOdd($value)' "></input>
  <pre>{{myform.value.$error|json}}</pre>
</form>

Doesn't get any simpler than that, and it's PROPER AngularJS validation (not silly watches)

Here's a working demo

ProLoser
  • 4,616
  • 2
  • 16
  • 23
  • 1
    this is exactly what I was looking for, thanks. Can you please add a working example? **I could not make your example work** – Scription Aug 09 '13 at 05:41
  • 1
    @Scription added. Looks like the stupid thing requires a *form* to work. Don't forgot the `ui.validate` module – ProLoser Aug 13 '13 at 01:05
3

Take a look at the angularjs form documentation - http://docs.angularjs.org/guide/forms . In general, it is based on the HTML5 attributes like required, min, max, etc.

To get, for example, your first requirement done - "an empty field should show "Field must contain a value" message, yo uwould do something like that:

<input type="text" ng-model="user.name" name="uName" required /><br />
<div ng-show="form.uName.$invalid">
  <span ng-show="form.uName.$error.required">Field must contain a value.</span>
</div>

For digits only field you can use the pattern attribute with a matching regular expression (example: http://www.wufoo.com/html5/attributes/10-pattern.html).

For even number validation, I'm not sure - I think you'd have to go with custom validation for that (meaning you'd have to create a directive) or use the pattern attribute somehow.

Last but not least - remember to add novalidate to the <form> tag. Otherwise the browser will try to validate your fields as well and you don't want that:

<form ... novalidate>
 ...
</form>
Shay Friedman
  • 4,808
  • 5
  • 35
  • 51
  • You answered my q only regarding "require" attribute. As for the rest, maybe I did not make my Q clear enough, I want to use JavaScript function that would make the correct validation on each user key press to the field (or leaving the field) – Scription Aug 08 '13 at 12:31
  • I wrote what should be done for the digits and even number validation - for digits you can use the pattern attribute (no need for custom JS function). For the even number validation, that's trickier and I don't think you will be able to get away without a directive. – Shay Friedman Aug 08 '13 at 12:36
  • I don't want to use directive at all ONLY JS – Scription Aug 08 '13 at 12:42
  • 3
    So why are you using angularjs if you don't wanna use its capabilities? – Shay Friedman Aug 08 '13 at 12:43
3

I know the question is old and I know you didn't want a directive but you may consider using a directive if it's "Angular" way... Well here is my Angular-Validation. I made a project on Github and I think that it just rocks compare to whatever is/was available...I based myself on the excellent Laravel PHP Framework and made it available under Angular... It is so crazy simple, you need 2 lines 1 line of code, 1 line for the input, 1 line for error display, that's it... never more and never less!!! Enough said, let's give some examples:

<!-- example 1 -->
<label for="input1">Email</label>
<input type="text" validation="email|min_len:3|max_len:25|required" ng-model="form1.input1" name="input1" />

<!-- example 2 -->
<label for="input2">Alphanumeric + Exact(3) + required</label>
<input type="text" validation="alpha|exact_len:3|required" ng-model="form1.input2" name="input2" />

So I can define whatever amount of validation rules (already 25+ type of validators) which I want in a simple directive validation="min_len:2|max_len:10|required|integer" and the error message will always display in the next <span> Don't you guys like it already? 1 line of code for your input, 1 line of code for the error display, you can't be simpler than that...oh and I even support your custom Regex if you want to add. Another bonus, I also support whichever trigger event you want, most common are probably onblur and onkeyup. Oh and I also support multiple localization languages via JSON external files. I really added all the imaginable features I wanted into 1 crazy simple directive.

No more clustered Form with 10 lines of code for 1 input (sorry but always found that a little extreme) when the only thing you need is 2 lines, no more, even for an input with 5 validators on it. And no worries about the form not becoming invalid, I took care of that as well, it's all handled the good "Angular" way.

Take a look at my Github project Angular-Validation... I'm sure you'll love it =)

UPDATE
Another candy bonus! To make an even more smoother user experience, I added validation on timer. The concept is simple, don't bother the user while he's typing but do validate if he makes a pause or change input (onBlur)... Love it!!!
You can even customize the timer as per your liking, I've decided to default it to 1 second within the directive but if you want to customize you can call as for example typing-limit="5000" to make a 5 sec. timeout. Full example:

<input type="text" ng-model="form1.input1" typing-limit="5000" validation="integer|required" name="input1" />
<span class="validation text-danger"></span>


UPDATE #2
Also added input match confirmation validation (ex.: password confirmation), here is a sample code

<!-- input match confirmation, as for example: password confirmation -->
<label for="input4">Password</label>
<input type="password" name="input4" ng-model="form1.input4" validation="alpha|min_len:4|required"  />
<label for="input4c">Password Confirmation</label>
<input type="password" name="input4c" ng-model="form1.input4c" validation="match:form1.input4,Password|required"  />

UPDATE #3
Refactored the directive so that the requirement of having a <span> to display the error is unnecessary, the directive now handles it by itself, see the code change reflected on top.

DEMO
Added a live demo on Plunker

ghiscoding
  • 12,308
  • 6
  • 69
  • 112
  • Thanks for the effort and plug-in – Scription Feb 09 '14 at 12:04
  • You're welcome, hope lot of people would use it and help me improve it... please note that I corrected a bug today which is maybe after you tried it, make sure you use latest code...Thanks... and I'm curious, would you use it? Do you like the concept? – ghiscoding Feb 09 '14 at 23:41
  • @ghiscoding I'm curious, why do you feel this approach is better than using ``? I think all the use-cases your project demos could be covered by these 3 attributes. – ProLoser Apr 29 '14 at 17:48
  • 1
    @ProLoser.. Because it's crazy simple, your code get shorter and you don't even need to write error messages as the directive does it for you. And now I just finished a candy bonus, to have smoother user experience I only validate after user inactivity. Love it =) – ghiscoding May 03 '14 at 02:44
2

Well you can try to create a func

<span ng-show='isEven(theText)'>Value must be an even number</span>

$scope.isEven=function(data) {
    if(data) {
        return data%2===0
    }
    return true;
}

The method can either be defined on the current controller scope or on $rootScope.

Not a very angular way, as directives would be better but i think it would work.

Chandermani
  • 42,589
  • 12
  • 85
  • 88
  • I want to use JavaScript and be able to change it instead of changing the HTML. however, if directive is the "Angular" way then I'm willing to consider it as well. **Can you please give me an example how to use it in directive?** – Scription Aug 08 '13 at 13:58
  • If you look at the angular developer guide for forms, and check for `custom validation` section you would see a working example there http://docs.angularjs.org/guide/forms – Chandermani Aug 08 '13 at 14:34