Wednesday, March 26, 2014

HTML Forms in AngularJS

This tutorial will show you how to collect and validate HTML form data using the two-way data binding of AnguarlJS. In this tutorial, we’ll learn how to implement a simple user registration form using Angular. Along the way, we’ll look at basic HTML and show what needs to be changed in order to incorporate AngularJS.

Prerequisities

Form HTML

The HTML for our signup form is shown below. Bootstrap has been used to make the site more visually appealing.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<html lang="en" ng-app="myApp">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap 101 Template</title>
    <link href="css/bootstrap.min.css" rel="stylesheet" />
    <link rel="stylesheet" href="css/app.css" />
  </head>
  <body>
    <form class="form-horizontal" role="form">
      <div class="form-group">
        <label for="inputName3" class="col-sm-2 control-label">Name</label>
        <div class="col-sm-4">
          <input class="form-control" id="inputName3" placeholder="Name">
        </div>
      </div>
      <div class="form-group">
        <label for="inputEmail3" class="col-sm-2 control-label">Email</label>
        <div class="col-sm-4">
          <input class="form-control" id="inputEmail3" placeholder="Email">
        </div>
      </div>
      <div class="form-group">
        <label for="inputPassword3" class="col-sm-2 control-label">Password</label>
        <div class="col-sm-4">
          <input class="form-control" id="inputPassword3" placeholder="Password">
        </div>
      </div>
      <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
          <button type="submit" class="btn btn-success">Sign up</button>
        </div>
      </div>
    </form>
    <script src="lib/common/jquery.min.js"></script>
    <script src="lib/common/bootstrap.min.js"></script>
    <script src="lib/angular/angular.js"></script>
    <script src="lib/angular/angular-route.js"></script>
    <script src="js/app.js"></script>
    <script src="js/services.js"></script>
    <script src="js/controllers.js"></script>
    <script src="js/filters.js"></script>
    <script src="js/directives.js"></script>
  </body>
</html>

The form should look like the following image.

Example Form

Collecting Data

In jQuery, individual form inputs are read using code like this:

1
$('#txtInput').val()
Because AngularJS supports two-way data binding, we don’t need to explicitly read the inputs. Instead, when the form input changes, it is automatically reflected in the controller’s $scope. To verify this, add the following span to the HTML before the closing form tag. This snipper relies on a variable named formInfo.

1
<span>{{formInfo}}</span>
AngularJS has a directive named ng-model which helps to bind an input to a variable. Let’s apply the ng-model directive to the three input elements in the form. Here is the updated HTML form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<form class="form-horizontal" role="form">
  <div class="form-group">
    <label for="inputName3" class="col-sm-2 control-label">Name</label>
    <div class="col-sm-4">
      <input class="form-control" id="inputName3" placeholder="Name" ng-model="formInfo.Name">
    </div>
  </div>
  <div class="form-group">
    <label for="inputEmail3" class="col-sm-2 control-label">Email</label>
    <div class="col-sm-4">
      <input class="form-control" id="inputEmail3" placeholder="Email" ng-model="formInfo.Email">
    </div>
  </div>
  <div class="form-group">
    <label for="inputPassword3" class="col-sm-2 control-label">Password</label>
    <div class="col-sm-4">
      <input type="password" class="form-control" id="inputPassword3" placeholder="Password" ng-model="formInfo.Password">
    </div>
  </div>
  <div class="form-group">
    <div class="col-sm-offset-2 col-sm-10">
      <button type="submit" class="btn btn-success">Sign up</button>
    </div>
  </div>
  <span>{{formInfo}}</span>
</form>
As you can see, the ng-model directive has been attached to each of the input elements. Each input is bound to a specific field in the formInfo object. Now, as the user enters data into the input elements, formInfo automatically gets updated. You can see this code in action by looking at this working demo. Using the same formInfo variable we can access the form data without reading each element value individually inside our controller. For that, we need to define a $scope.formInfo variable inside our controller, MyCtrl1. After making these changes, this is what app/js/controllers.js looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
'use strict';
/* Controllers */
angular.module('myApp.controllers', []).
  .controller('MyCtrl1', ['$scope', function($scope) {
    $scope.formInfo = {};
    $scope.saveData = function() {
    };
  }])
  .controller('MyCtrl2', [function() {
  }]);

We have also defined a function named saveData() which will be called when the user clicks the Sign Up button.

Next, we need to attach a ng-controller directive to the form itself.

1
<form class="form-horizontal" role="form" ng-controller="MyCtrl1">
Next, attach a ng-click directive to the Sign Up button:

1
<button type="submit" ng-click="saveData()" class="btn btn-success">Sign up</button>
Inside the saveData() function, add a console.log($scope.formInfo); just to check if we are getting the form data collection in our controller using the $scope. Restart the node server, browse to the HTML page, and check your browser console. You should see some thing like this:

1
Object {Name: "Jay", Email: "jay3dec@gmail.com", Password: "helloworld"}

Now, this collected data can be stored in a database.

Validating the Inputs

We also need to validate, if the data that we received from the $scope is valid. If it’s not, we must show some validation errors. The ng-show directive shows or hides an element based on the value of an expression. We’ll be using it to show error messages. Begin by defining three $scope variables – $scope.nameRequired, $scope.emailRequired, and $scope.passwordRequired. We’ll validate the name, email, and password in the saveData() function as shown in the updated app/js/controllers.js.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
'use strict';
/* Controllers */
angular.module('myApp.controllers', [])
  .controller('MyCtrl1', ['$scope', function($scope) {
    $scope.formInfo = {};
    $scope.saveData = function() {
      $scope.nameRequired = '';
      $scope.emailRequired = '';
      $scope.passwordRequired = '';
      if (!$scope.formInfo.Name) {
        $scope.nameRequired = 'Name Required';
      }
      if (!$scope.formInfo.Email) {
        $scope.emailRequired = 'Email Required';
      }
      if (!$scope.formInfo.Password) {
        $scope.passwordRequired = 'Password Required';
      }
    };
  }])
  .controller('MyCtrl2', [function() {
  }]);

In the HTML page, add a span for each input element to display error message as shown below;

1
2
3
<span ng-show="nameRequired">{{nameRequired}}</span>
<span ng-show="nameRequired">{{emailRequired}}</span>
<span ng-show="nameRequired">{{passwordRequired}}</span>

Restart the node server and try to click the Sign Up button with empty input elements. You should see the appropriate error messages.

Source: Site Point

13 comments:

  1. Node is NOT a requirement for AngularJS nor the AngularJS seed project.

    ReplyDelete
  2. Just use ng-required="true" and $scope.formname.$valid to check if the form is valid. Check the docs here for more validation options http://docs.angularjs.org/api/ng/directive/input

    ReplyDelete