AngularJS: Controller Tutorial

AngularJS: Controller Tutorial

In this tutorial we will discuss one of AngularJS’s most useful features — the Controller. This is the second in a series of tutorials on AngularJS where we will be discussing many of the useful features found in this SPA (single page application) framework. In our last tutorial we saw Introduction and Sample Programs where we created our Hello World using AngularJS. We were also introduced to several directives including ng-app, ng-model and various filters (including currency, number, date, uppercase, lowercase and limitTo).

1. What are Controllers?

According to AngularJS documentation, a Controller is a JavaScript constructor function used to augment the Angular Scope. But we should think of the controller as nothing more than a container that will contain some logic for driving certain things in the view. Let’s dive in with some more information. In this tutorial we will discuss, in a little more detail, the Model, View and Controller. In addition, we will be discussing Scope — another term for this is ViewModel. If you remember, in the previous tutorial you saw all of the code being maintained in the View (the html pages) that defined our directives, filters and data bindings. Now, while that was fine for the introductory part of the lesson, we typically do not want to put all of our logic in the View because it isn’t very maintainable or even testable as the applications grow and get larger. Instead, what Angular recommends is that we create a special little object, a container, called a Controller which will “glue” the Model (data) to the View.

2. What are Scopes?

Scope is nothing more than an object that ties the View to the Controller. It is literally the “glue” that binds the controller to the view and vice versa, in Angular, this object is defined as $scope. The view doesn’t have to know about the controller and the controller does not need to know about the view. Again, just think about it as an object that links the View to the Controller. Let’s looks at our SimpleBooksController to help you understand this concept. But instead of having our controller just have the model(data) we will also have an addBooks method that will allow you, the user interact with the model and add additional books into our library.

2.1 ng-controller

This directive defines a Controller to be bound with a View. In the following example, we defined the SimpleBooksController using ng-controller directive in the DIV tag in line 11. We say that SimpleBooksController’s scope lies between the two <div> … </div> tags.

<div ng-controller="SimpleBooksController">
  .....
  .....
  .....
</div>

2.2 ng-click

The ng-click directive is used to fire an event and call the addBook function which will insert the fields (title, author, price and isbn) from the newbook object into the books array. This function will also clear out the newbook object so that user may enter another book using the data entry form.

<button ng-click="addBook()">Add Book</button>

2.3 ng-repeat

ng-repeat is used to iterate through our array of books (which is sorted by title) and in our example, it will create the rows and columns in the HTML table. As it loops through each element in the array it puts the title, author, price and isbn into the appropriate columns creating the finished look.

<tr ng-repeat="book in books | orderBy: 'title'">

2.4 Simple Books Embedded Controller

<!DOCTYPE html>
<html ng-app>
  <head>
      <title>Simple Embedded Angular Controller</title>
      <link rel="stylesheet" type="text/css" href="include/styles.css">
      <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js">
      </script>
  </head>

  <body>
    <div ng-controller="SimpleBooksController" >
      <table>
        <tr>
          <th>Title</th>
          <th>Author</th>
          <th>Price</th>
          <th>ISBN</th>
        </tr>
        <tr>
          <td><input type="text" ng-model="newbook.title"></td>
          <td><input type="text" ng-model="newbook.author"></td>
          <td><input type="text" ng-model="newbook.price"></td>
          <td><input type="text" ng-model="newbook.isbn"></td>
        </tr>
        <tr>
          <td colspan="4"><button ng-click="addBook()">Add Book</button></td>
        </tr>
      </table>
      <br><br>
      <table>
        <tr>
          <th>Title</th>
          <th>Author</th>
          <th>Price</th>
          <th>ISBN</th>
        </tr>
        <tr ng-repeat="book in books | orderBy: 'title'">
          <td>{{ book.title }}</td>
          <td>{{ book.author }}</td>
          <td>{{ book.price | currency}}</td>
          <td>{{ book.isbn }}</td>
        </tr>
      </table>
    </div>
    <script type="text/javascript">
      function SimpleBooksController($scope) {
        $scope.books = [
          {
            title: 'Charlottes Web',
            price: 6.35,
            isbn: '978-0739477076',
            author: 'E. B. White'
          },
          {
            title: 'Great Expectations',
            price: 2.87,
            isbn: '978-0486415864',
            author: 'Charles Dickens'
          },
          {
            title: 'Harry Potter and the Sorcerers Stone',
            price: 6.92,
            isbn: '978-0590353427',
            author: 'J.K. Rowling'
          },
          {
            title: 'Moneyball: The Art of Winning an Unfair Game',
            price: 9.01,
            isbn: '978-0393324815',
            author: 'Michael Lewis'
          }
        ];

        $scope.addBook = function() {
          $scope.books.push($scope.newbook);
          $scope.newbook = {};
        }
      }
    </script>
  </body>
</html>

2.2 TRY ME — Live Demo

3. What are Modules?

angularJS_ControllerThe above example is fine for introduction into some of the key AngularJS concepts like: directives, controllers, filters, etc. but in actually, this embedded approach does not scale well. In addition, using modules makes your code more maintainable, readable and testable. An AngularJS module is nothing more than a container that let’s you define and organize all of the components like controllers, services, filters, and directives.

Benefits of Modules

  • It makes your View far easier to read and less cluttered
  • You can reuse modules in several HTML pages easily (View)
  • Modules can be loaded in any order

In this example, “app.js” contains the application module definition using angular.module. As you can see, I decided to call my module “store”. This module contains a controller called BooksController and an array of books.

3.1 Understanding app.js Module

(function() {
    var app=angular.module('store', []);

    app.controller('BooksController', function() {
        this.products = books;
    });

    var books = [
    {
        title: 'Charlottes Web',
        price: 6.35,
        description: 'An affectionate, sometimes bashful pig named Wilbur befriends a spider named Charlotte, who lives in the rafters above his pen. A prancing, playful bloke, Wilbur is devastated when he learns of the destiny that befalls all those of porcine persuasion. Determined to save her friend, Charlotte spins a web that reads "Some Pig," convincing the farmer and surrounding community that Wilbur is no ordinary animal and should be saved. In this story of friendship, hardship, and the passing on into time, E.B. White reminds us to open our eyes to the wonder and miracle often found in the simplest of things.',
        isbn: '978-0739477076',
        author: 'E. B. White',
        publisher: 'Harper Collins',
        canPurchase: true,
        soldOut: false
    },
    {
        title: 'Great Expectations',
        price: 2.87,
        description: 'An absorbing mystery as well as a morality tale, the story of Pip, a poor village lad, and his expectations of wealth is Dickens at his most deliciously readable. The cast of characters includes kindly Joe Gargery, the loyal convict Abel Magwitch and the haunting Miss Havisham. If you have heartstrings, count on them being tugged.',
        isbn: '978-0486415864',
        author: 'Charles Dickens',
        publisher: 'Dover Publications',
        canPurchase: true,
        soldOut: false
    },
    {
        title: 'Harry Potter and the Sorcerers Stone',
        price: 6.92,
        description: 'Harry Potter has no idea how famous he is. That is because he is being raised by his miserable aunt and uncle who are terrified Harry will learn that he is really a wizard, just as his parents were. But everything changes when Harry is summoned to attend an infamous school for wizards, and he begins to discover some clues about his illustrious birthright.',
        isbn: '978-0590353427',
        author: 'J.K. Rowling',
        publisher: 'Scholastic',
        canPurchase: true,
        soldOut: false
    },
    {
        title: 'Beloved',
        price: 8.75,
        description: 'In the troubled years following the Civil War, the spirit of a murdered child haunts the Ohio home of a former slave. This angry, destructive ghost breaks mirrors, leaves its fingerprints in cake icing, and generally makes life difficult for Sethe and her family; nevertheless, the woman finds the haunting oddly comforting for the spirit is that of her own dead baby, never named, thought of only as Beloved. ',
        isbn: '978-1400033416',
        author: 'Toni Morrison',
        publisher: 'Dover Publications',
        canPurchase: true,
        soldOut: false
    },
    {
        title: 'Moneyball: The Art of Winning an Unfair Game',
        price: 9.01,
        description: 'Billy Beane, general manager of MLBs Oakland As and protagonist of Michael Lewis Moneyball, had a problem: how to win in the Major Leagues with a budget that is smaller than that of nearly every other team. Conventional wisdom long held that big name, highly athletic hitters and young pitchers with rocket arms were the ticket to success. But Beane and his staff, buoyed by massive amounts of carefully interpreted statistical data, believed that wins could be had by more affordable methods such as hitters with high on-base percentage and pitchers who get lots of ground outs. Given this information and a tight budget, Beane defied tradition and his own scouting department to build winning teams of young affordable players and inexpensive castoff veterans. ',
        isbn: '978-0393324815',
        author: 'Michael Lewis',
        publisher: 'W. W. Norton & Company',
        canPurchase: true,
        soldOut: false
    }
    ]
})();

3.2 Looking at the View in our integrated example

This first thing you will notice in our example is that the ng-app syntax has now changed and now contains ng-app=”store” where store is the moduleName. This will bootstrap the application with the required module. Simple and elegant!

You will also note, that I added app.js in line 8 of the view. Finally, I would like to point out that I added style.css but this is only for aesthetics reasons as I wanted to table to appear in two-tone green with alternating row colors. Now our view appears much less cluttered and is certainly more maintainable than the previous example.

<!DOCTYPE html>
<html ng-app="store">
<head>
  <title>Angular Controller Directive</title>
  <link rel="stylesheet" type="text/css" href="include/styles.css">
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js">
  </script>
  <script type="text/javascript" src="include/app.js">
</head>

<body>
  </script>
    <div ng-controller="BooksController as store" >
      <table class="striped">
        <tr>
          <th>Title</th>
          <th>Author</th>
          <th>Price</th>
          <th>ISBN</th>
          <!-- <th width="400">Description</th> -->
        </tr>
        <tr ng-repeat="book in store.products | orderBy: 'title'">
          <td>{{ book.title }}</td>
          <td align="center">{{ book.author }}</td>
          <td align="right">{{ book.price | currency}}</td>
          <td align="center">{{ book.isbn }}</td>
          <!-- <td>{{ book.description }}</td> -->
        </tr>
      </table>
    </div>
</body>
</html>

3.3 Adding a Cascading Stylesheet to enhance the look of our table

table {
    width:700px;
}
table, th, td {
    border: 1px solid black;
    border-collapse: collapse;
}
th, td {
    padding: 5px;
    text-align: left;
}
table.striped tr:nth-child(even) {
    background-color: #ECFBE6;
}
table.striped tr:nth-child(odd) {
   background-color:#ffffff;
}
table.striped th    {
    background-color: #92E86F;
}

3.4 Sample Output

books_controller

What Next?

Till now, the data has been pretty static. We have been defining the model and the complete data set either inside the View or the Controller (ViewModel). The way that we have done it is by creating a static array with all the data elements predefined. In order to adhere to the Single Responsibility Principle we should ensure that our controller does just one thing and we would make use of a service and use AJAX or JSON in order to pull down data in real-time.

Our next tutorial will feature details on using Services using AngularJS.

 

Please Share Us on Social Media

Facebooktwitterredditpinterestlinkedinmail

Leave a Reply

Your email address will not be published. Required fields are marked *