I would like to use this article to talk about Ionic Framework form handling and validation. I will demonstrate it by building a simple login application, it’s simply one of an easiest examples of form manipulations.
 
Form handling in Ionic Framework is straightforward as it gets; I will talk about it briefly. On the other hand, form validation is a completely different story. Simple out of the box solution didn’t exist before AngularJS 1.3.0. Before that time, you could have used countless custom angular directives, but each solution had its set of rules and problems.
 
Angular 1.3.0 came and gave us a ngMessages module. This module provides enhanced support for displaying messages within templates (typically within forms or when rendering message objects that return key/value data). Instead of relying on JavaScript code and/or complex ng-if statements within your form template to show and hide error messages specific to the state of an input field, the ngMessages and ngMessage directives are designed to handle the complexity, inheritance and priority sequencing based on the order of how the messages are defined in the template.
 
Since Beta 14 it’s also available for Ionic Framework (this version included AngularJS 1.3).
 
 

Note: If this tutorial was helpful, need further clarification, something is not working or do you have a request for another Ionic post? Furthermore, if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here, again leave me a comment below. I'm here to help you, I expect the same from you. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com, or follow and mention me on twitter (@gajotres). Thanks and have a nice day!

PS. If you want my help, if possible (even if it takes you some time to do that), create a working example I can play with. Use Plunker for AngularJS based questions or jsFiddle for jQuery/jQuery Mobile based questions.


 
Update: This article is now updated to support Ionic 1.0.1. and latest version of ngMessages. This example will no longer work with ngMessages version 1.3.X and below.
 

Table of Contents

Click here if you want to see other tutorials; or articles about Ionic themes, templates, plugins ...

Example

 
Just like in my previous articles I will start with working example. Below you’ll find a direct link to working Plnkr example, or you can play with it directly in an embedded application.
 
Demo
 
Embeded working example
 
Ionic Framework authorization example
 
HTML
<html ng-app="starter">
 
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
  <title>Ionic Framework Example</title>
  <link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet"/>
  <link href="style.css" rel="stylesheet"/>
  <script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-messages.js"></script>  
  <script src="script.js"></script>
</head>
 
<body>
  
  <ion-nav-bar class="bar-positive">
    <ion-nav-back-button class="button-clear">
      <i class="ion-arrow-left-c"></i> Back
    </ion-nav-back-button>
  </ion-nav-bar>
  
  <ion-nav-view></ion-nav-view>
  
  <script id="auth.html" type="text/ng-template">
    <ion-view view-title="Authorization Page">  
    
      <ion-content class="padding">
      
        <h2 style="text-align: center;">Form validation example</h2><br/>
        
        <form name="authorizationForm" novalidate="" ng-submit="signIn(authorizationForm)"> 
        
          <div class="list">
          
            <label class="item item-input" ng-class="{ 'has-errors' : authorizationForm.username.$invalid, 'no-errors' : authorizationForm.username.$valid}">
              <span class="input-label">Username</span>
              <input type="text" name="username" ng-model="authorization.username" ng-minlength="5" ng-maxlength="20" required>
            </label>
            
            <div class="error-container" ng-show="authorizationForm.username.$error" ng-messages="authorizationForm.username.$error">
              <div ng-messages-include="error-list.html"></div>
            </div>
            
            <label class="item item-input" ng-class="{ 'has-errors' : authorizationForm.password.$invalid && authorizationForm.$submitted, 'no-errors' : authorizationForm.password.$valid  && authorizationForm.$submitted}">
              <span class="input-label">Password</span>
              <input type="password" name="password" ng-model="authorization.password" ng-minlength="5" ng-maxlength="20" required>
            </label>
            
            <div class="error-container last-error-container" ng-show="authorizationForm.password.$error && authorizationForm.$submitted" ng-messages="authorizationForm.password.$error">
                <div ng-messages-include="error-list.html"></div> 
            </div>          
            
          </div>     
          
          <button class="button button-full button-positive" type="submit">
            Sign In
          </button>
            
        </form>   
        
      </ion-content>
      
    </ion-view>
  </script>  
  
  <script id="home.html" type="text/ng-template">
    <ion-view view-title="Second page">
      <ion-content class="padding">
          <h1>Wellcome</h1>
      </ion-content>
    </ion-view>
  </script>   
  
  <script id="error-list.html" type="text/ng-template">  
    <div class="error" ng-message="required">
      <i class="ion-information-circled"></i> 
      This field is required!
    </div>
    <div class="error" ng-message="minlength">
      <i class="ion-information-circled"></i> 
      Minimum length of this field is 5 characters!
    </div>
    <div class="error" ng-message="maxlength">
      <i class="ion-information-circled"></i> 
      Maximum length of this field is 20 characters!
    </div>
  </script>   
  
</body>
 
</html>
JavaScript
var nameApp = angular.module('starter', ['ionic', 'ngMessages']);

nameApp.config(function($stateProvider, $urlRouterProvider) {
 
  $stateProvider
    .state('auth', {
      url: '/auth',
      templateUrl: 'auth.html',
      controller: 'AuthCtrl'
    })
    .state('home', {
      url: '/home',
      templateUrl: 'home.html',
      controller: 'HomeCtrl'
    });
 
  $urlRouterProvider.otherwise("/auth");
 
});


nameApp.controller('AuthCtrl', function($scope, $state) {
  
  $scope.authorization = {
    username: '',
    password : ''    
  };  
  
  $scope.signIn = function(form) {
    if(form.$valid) {
      $state.go('home');
    }
  };  

});
 
nameApp.controller('HomeCtrl', function($scope) {

});
CSS
.error-container {
  margin: 5px 0;
}

.error-container:last-child {
    margin: 5px 0 0;
}

.error {
  padding: 10px 16px;
  font-family: "Arial Black", Gadget, sans-serif;
  font-size: 11px;
  text-transform: uppercase;
  color: #555;
  vertical-align: middle;
}

.error i {
  font-size: 24px;
  color: #B83E2C;  
  vertical-align: middle;
}

.last-error-container > .error {
  padding: 10px 16px 0;
}

.has-errors {
  border-bottom: 3px solid #B83E2C;
}

.no-errors {
  border-bottom: 3px solid green;
}

Before form is submitted

 
Before we can do anything we need to inject ngMessages module into our application (don’t forget to initialize angular-messages.js file before):
 
var nameApp = angular.module('starter', ['ionic', 'ngMessages']);
 
Application will have two input fields and one submit button. One field will cover username and a second one will cover a password. When form loads, application will automatically validate an username field while click on a submit button will initiate a manual form validation process.
 
Let’s see what’s happening on a first field (it will be validated after application is successfully initialized):
 
<form name="authorizationForm" novalidate="" ng-submit="signIn(authorizationForm)">

  <div class="list">

    <label class="item item-input" ng-class="{ 'has-errors' : authorizationForm.username.$invalid, 'no-errors' : authorizationForm.username.$valid}">
      <span class="input-label">Username</span>
      <input type="text" name="username" ng-model="authorization.username" ng-minlength="5" ng-maxlength="20" required>
    </label>

    <div class="error-container" ng-show="authorizationForm.username.$error" ng-messages="authorizationForm.username.$error">
      <div ng-messages-include="error-list.html"></div>
    </div>

    <label class="item item-input" ng-class="{ 'has-errors' : authorizationForm.password.$invalid  && authorizationForm.$submitted, 'no-errors' : authorizationForm.password.$valid  && authorizationForm.$submitted}">
      <span class="input-label">Password</span>
      <input type="password" name="password" ng-model="authorization.password" ng-minlength="5" ng-maxlength="20" required>
    </label>

    <div class="error-container last-error-container" ng-show="authorizationForm.password.$error && authorizationForm.$submitted" ng-messages="authorizationForm.password.$error">
      <div ng-messages-include="error-list.html"></div>
    </div>

  </div>

  <button class="button button-full button-positive" type="submit">
    Sign In
  </button>

</form>
 
Form must have a name attribute. It should also have a function that will be called during a form submit event:
 
<form name="authorizationForm" novalidate="" ng-submit="signIn(authorizationForm)"> 
 
Every field will need to be set manually depending on application needs. This article example will cover three checks:
 
  1. requirement
  2. min length
  3. max length
<input type="text" name="username" ng-model="authorization.username" ng-minlength="5" ng-maxlength="20" required>
 
Separate template will hold our error messages. There will be three of them, one per field check:
 
<script id="error-list.html" type="text/ng-template">  
	<div class="error" ng-message="required">
		<i class="ion-information-circled"></i> 
		This field is required!
	</div>
	<div class="error" ng-message="minlength">
		<i class="ion-information-circled"></i> 
		Minimum length of this field is 5 characters!
	</div>
	<div class="error" ng-message="maxlength">
		<i class="ion-information-circled"></i> 
		Maximum length of this field is 20 characters!
	</div>
</script>   
 
Continue Reading

  • Thanks man! This article was very useful for me. I made some changes in the way to show messages, I put the messages in the end of the screen and set the warning icon inside the field.

  • Valerio

    You save my life. Thanks

  • p3

    Angular-messages are updated now and ng-messages-include must be seperate. Update your article please. It helped me very much, but that point made me stuck.

    • Wow, that was nice of you, I need to remember to ask other to do the same thing if or when they find something outdated. Regarding outdated content, I’ll update it tonight.

  • Hamad Alwahbi

    How to reset the form after submit ?

    • Sorry for a late response, I missed this question somehow. You can empty form easily, in case of my example before you transition to next page you can use $scope.authorization = {};. Or you can use Ionic view events and clear the form every time page (view) loads.

  • Derek Hannah

    instead of using things like “required” or “minlength”, can you use a custom variable? or expression?

  • Swati Jaiswal

    hey, nice post but I was facing a little problem. see if you could help. In the html you have passed form name as an argument to the function called on ng-submit and in the controller you are checking for form.$valid in the function. I did the same but it gives error that form is undefined. What a possible problem could be ?

    • Do you maybe have a working example of your code? It’s really hard to comment anything without the code.

      • Swati Jaiswal

        sorry to bother you. It was a little mistake, My submit button on which the form was submitted was outside the form. I was trying to send the form from that which didn’t recognize it. I got it resolved. Thanks.

        • No problem, I’m glad to be of help. Could you tell me one thing, while going through this article, have you found something worth improving? I just want to know if anything is missing?

          • Swati Jaiswal

            yes sure. The post was very helpful. One thing in which I faced a little problem was that the article covers one page app. While everyone out there most probably will be building some production app. So if you could split the code in files then it will make more sense to those. As i was one of them and it took much time for me to understand things at first. One more thing you suggested in comments below for custom variables, could you please include it in the post. Otherwise the post was good enough.

  • Nicolás David

    Hi, good tutorial, thank you a lot. I was wondering if there is a way to validate the fields only after the user clicks on the field by the first time. I do not want to show that every field on my form is wrong right when it is loaded. Thank you in advance.

    • Isn’t this a little bit unproductive? No point on doing that on a first click because application user still haven’t had time to write anything. Maybe on the lost focus? That’s doable, if you need such example I can write it for you, lets say tomorrow.

      • Warren On Show

        You can mark the field as edited when ng-change is fired. Or even better, you can use authorizationForm.username.$pristine or authorizationForm.username.$touched (which are updated automatically by Angular when the field is edited).

  • Rasheed

    This was a great Tutorial and helped out big Time!

  • Nency Bhalala

    Great tutorial… It works fine in browser, but then i created android apk and the apk stopped working..

  • David

    IONIC IS AWESOME

  • code examples require 4k wide screen…. frustrating

    • It’s better to have any code then none, then again you can always play with plnkr example

  • sushilbansal1982

    Hi, problem i am facing is before even submitting user is seeing the error like This is a required field. Is there a way by which only when user click on submit he can see the errors. Not before that.

  • Amila Udana Kalinga

    If form values set by controller on load, this does not work. How to make required fields validated ?

    • Amila Udana Kalinga

      figured it out it should be the same name in model when promise set. thanks

  • Isuru Amantha

    Good tutorial. work as charm

  • Flex

    Thanks Gajotres,

    But, How I can check with alert message.

    Please help.

    Thanks in advance.