I would like to use this article to talk about OnsenUI 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 OnsenUI 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.
 
 

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.


 

Table of Contents

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
 
Embedded working example
 
OnsenUI form handling and validation example
 

HTML:

<html>

<head>
  <script src="https://code.angularjs.org/1.3.0/angular.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular-messages.min.js"></script>    
  <script src="http://onsenui.io/OnsenUI/build/js/onsenui.js"></script>
  <script src="script.js"></script>
  <link rel="stylesheet" href="https://cdn.rawgit.com/OnsenUI/OnsenUI/1.2.2/build/css/onsenui.css" />
  <link rel="stylesheet" href="https://cdn.rawgit.com/OnsenUI/OnsenUI/1.2.2/build/css/onsen-css-components.css" />
  <link rel="stylesheet" href="style.css" />
</head>

<body ng-controller="ListCtrl">

  <ons-navigator animation="slide" var="app.navi">
    <ons-page>
      <ons-toolbar class="toolbar-black">
        <div class="center">First Page</div>
      </ons-toolbar>
      <h2 style="text-align: center;">Form handling and validation example</h2><br/>

      <form name="authorizationForm" novalidate="" ng-submit="signIn(authorizationForm)"> 

        <ul class="list">
          <li class="list__header">Enter an Email Adress</li>
        </ul>
        <input type="text" 
               name="email" 
               value="" 
               ng-model="authorization.email" 
               ng-minlength="5" 
               ng-maxlength="40" 
               ng-pattern="/^[_a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/" 
               required 
               ng-class="{ 'has-errors' : authorizationForm.email.$invalid, 'no-errors' : authorizationForm.email.$valid}" 
               ng-messages-include="error-list.html" 
               placeholder="Enter an Email Adress" 
               class="text-input text-input--underbar" 
               style="width: 96%; margin: 2%;">
  
        <div class="error-container" ng-show="authorizationForm.email.$error" ng-messages="authorizationForm.email.$error" ng-messages-include="error-list.html">
        
        </div>     
  
        <ons-row class="profile-wrapper" style="padding: 10px;">
          <button class="button button--large--cta" type="submit">Retrieve Password</button>
        </ons-row>    

      </form>     
     
    </ons-page>   
  </ons-navigator>    
   
  <ons-template id="view.html">
    <ons-page ng-controller="ViewCtrl">
      <ons-toolbar>
        <div class="left" style="line-height: 44px">
          <ons-back-button>Back</ons-back-button>
        </div>        
        <div class="center">Second Page</div>
      </ons-toolbar>

      <h3 style="padding: 10px;">You have sucesfully validated application form</h3>

    </ons-page>
  </ons-template>
  
  <ons-template id="error-list.html">  
    <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 40 characters!
    </div>
    <div class="error" ng-message="pattern">
      <i class="ion-information-circled"></i> 
      Wrong email pattern!
    </div>  
  </ons-template>    
  
</body>
</html>

JavaScript:

var module = ons.bootstrap('my-app', ['onsen', 'ngMessages']);

module.controller('ListCtrl', function($scope) {

  $scope.authorization = {
    email: ''
  };  
  
  $scope.signIn = function(form) {
    if(form.$valid) {
      app.navi.pushPage("view.html", { animation: "lift"});
    }
  }; 
  
});

module.controller('ViewCtrl', function($scope) {
  
});

CSS:

.error-container {
  margin: 5px 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;
}

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

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

 

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 module = ons.bootstrap('my-app', ['onsen', 'ngMessages']);

 
An application will have one input field (email) and one submit button. When form loads, application will automatically validate an email field while click on a submit button will initiate a manual form validation process.
 
Let’s see what’s happening in email field (it will be validated after application is successfully initialized):
 
<form name="authorizationForm" novalidate="" ng-submit="signIn(authorizationForm)"> 

	<ul class="list">
		<li class="list__header">Enter an Email Adress</li>
	</ul>
	<input type="text" name="email" value="" ng-model="authorization.email" ng-minlength="5" ng-maxlength="40" ng-pattern="/^[_a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/" required ng-class="{ 'has-errors' : authorizationForm.email.$invalid, 'no-errors' : authorizationForm.email.$valid}" ng-messages-include="error-list.html" placeholder="Enter an Email Adress" class="text-input text-input--underbar" style="width: 96%; margin: 2%;">

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

	</div>     

	<ons-row class="profile-wrapper" style="padding: 10px;">
		<button class="button button--large--cta" type="submit">Retrieve Password</button>
	</ons-row>    

</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 four checks:
 
  1. requirement
  2. min length
  3. max length
  4. correct email pattern
They should look like this:
 
<input type="text" 
       name="email" 
	   value="" 
	   ng-model="authorization.email" 
	   ng-minlength="5" 
	   ng-maxlength="40" 
	   ng-pattern="/^[_a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/" 
	   required 
	   ng-class="{ 'has-errors' : authorizationForm.email.$invalid, 'no-errors' : authorizationForm.email.$valid}" 
	   ng-messages-include="error-list.html" 
	   placeholder="Enter an Email Adress" 
	   class="text-input text-input--underbar" 
	   style="width: 96%; margin: 2%;">
 
Separate template will hold our error messages. There will be four of them, one per field check:
 
<ons-template id="error-list.html">  
	<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 40 characters!
	</div>
	<div class="error" ng-message="pattern">
		<i class="ion-information-circled"></i> 
		Wrong email pattern!
	</div>  
</ons-template> 
 
By default, ngMessages will only display one error at a time. However, if you wish to display all messages then the ng-messages-multiple attribute flag can be used on the element containing the ngMessages directive to make this happen.
 
Continue Reading