KodeInfo | Learning resources for web and mobile development

AngularJs Controllers

December 27th, 2014 09:42:55 in Controllers by Imran Iqbal Comments(0) - Views(6031)
Tags : angularjs, Controllers, Views, data binding, Models, scopes, directives

 Let's talk about one of the AngularJs most useful feature which helps us in making awesome single page application in JavaScript -  Controllers.

This tutorial is part of series of tutorials on AngularJs where we will look into different aspects of AngularJs and it's features. In our last tutorial we saw Introduction of AngularJs and also created a Hello World example using two way data binding feature of Angular.

Controllers are nothing but plain JavaScirpt functions which are bound to a particular scope. Controllers are used to add logic to your view. Views are nothing but HTML templates. These templates shows the data that we bind to them using two-way data binding in Angular. Controllers functionality is nothing but to glue the Model (data) with the View.

What are Scopes?

Before we get into Controllers let us understand Scopes. Scope is nothing but an object that glues the View with Controller. They hold the Model data that we need to pass to view. Scope uses Angular's two-way data binding to bind model data to view.

Let's write a simple Hello World application to understand $scope object.

<!DOCTYPE html>
<html>

<head>
	<title> Simple App</title>
	<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>

<body>
	<div ng-controller="ContactController" class="ng-scope" ng-app>
	     Email:<input type="text" ng-model="newcontact" class="ng-pristine ng-valid">
	    <button ng-click="add()">Add</button>
	    <h2>Contacts</h2>
	 
	    <ul>
	        <!-- ngRepeat: contact in contacts -->
	        <li ng-repeat="contact in contacts" class="ng-scope ng-binding"> {{ contact }} </li>	   
	    </ul>
	 
	</div>
	
</body>

<script type="text/javascript">
	function ContactController($scope){
		$scope.contacts=["hi@email.com","hello@email.com"];
		$scope.add=function(){
			$scope.contacts.push($scope.newcontact);
			$scope.newcontact="";
		}
	}
</script>
</html>

                                                      

First thing we have to notice in the above example is attribute called ng-controller.

ng-controller

This attribute defines a Controller to be bound with the view. In this case we defined a controller called ContactController  using ng-controller attribute.  In demo we defined a function, which is plain JavaScript function. There is an object $scope which we pass as an argument. This object is used to bind the controller with view. When AngularJs initialize this controller, it automatically creates and injects the $scope object to this function using dependency injection ( this will be explained in future tutorials). 

ng-repeat

It's to loop through list of contacts.

ngRepeat: contact in contacts

ngRepeat iterate through an array and bind the view with each element. So in our example it creates tag for each item within contacts array. ngRepeat takes expression as argument. In our demo example "contact in contacts" where contact is user defined variable and contacts is an rray within $scope object.

Initial State of a scope object

 Typically, when we create an application we setup some initial state for an Angular scope. In our case we need initial state to be list of contacts.

on $scope object, we defined an array called contacts.

$scope.contacts=["hi@email.com","hello@email.com"];

When Angular initialize this function (ContactController), it automatically creates this array and binds it in $scope object. Then in our view we display the array using ng-repeat​ attribute.

$scope provides us with a way to pass/retrieve objects from Controller to View and vice versa.

ng-click

It is also possible to define functions on $scope and use the same in View. In our demo, we created a function add() on $scope  and use it on Add button click.

$scope.add=function(){
			$scope.contacts.push($scope.newcontact);
			$scope.newcontact="";
		}

The function add() is bound to Add button using an attribute ng-click. ng-click binds the click event on the button or link or any clickable element with the function that is defined within $scope. So in this case whenever Add button is clicked, the add() function will be called.

In add() function we add a string in contacts array. This is the string which user enters in the textbox. Note that we bind textbox using ng-model attribute. 

How to define a Controller

So we got some basic idea now how to define controllers are. Controller is  just plain JavaScript functions that we add in Angular application to add some business logic and also to bind the View with the Model.

In the above demo we defined controller as a JavaScript function. While that is so easy but what happens when there are so many functions, they mess up with your JavaScipt Namespace. So instead of defining controller as :

function ContactController($scope) 
{

 ////////

}

We should define them within Modules.

AngularJs Modules

Modules are logic entities that we divide our app into different parts like transaction, reports etc. So your app can contain several modules. Each module represents a logic entitiy within the app.

                          

A module can contain several controllers and views. We will see how a module can be linked with view using Routing in AngularJs in our next tutorial. For now we can link one or more views to a single controller.

Lets us define a module and add controlelr to it.

var myApp = angular.module('myApp',[]);
  
myApp.controller('ContactController', ['$scope', function($scope) {
    $scope.contacts = ["hi@email.com", "hello@email.com"];
 
    $scope.add = function() {
        $scope.contacts.push($scope.contact);
        $scope.contact = "";
    }
}]);

In the above example we created a modeule called myApp using angular.module() method. Then we added a controller called ContactController to this module. 

Now how controller was defined using myApp.controller() method. We passed an array to this method. First argument of array is string $scope and next is the function itself that represent ContactController. We explicitly told to the angular that we have an argument to our ContactController which $scope.

Nested Controllers

We can declare controllers within another controller and we can control the scope of one controller using an attribute called ng-scope

<!DOCTYPE html>
<html>

<head>
	<title> Simple App</title>
	<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>

<body>
	<div ng-app="" ng-controller="CarController">
    My name is {{ name }} and I am a {{ type }}
     
    <div ng-controller="BMWController">
        My name is {{ name }} and I am a {{ type }}
 
        <div ng-controller="BMWMotorcycleController">
            My name is {{ name }} and I am a {{ type }}
 
        </div>
    </div>
</div>
	
</body>

<script type="text/javascript">
	function CarController($scope) {
 
    $scope.name = 'Car';
    $scope.type = 'Car';
 
}
 
function BMWController($scope) {
 
    $scope.name = 'BMW';
 
}
 
function BMWMotorcycleController($scope) {
 
    $scope.name = 'BMWMotorade';
    $scope.type = 'Motorcycle';
 
}
</script>
</html>

                                                    

This way we can declare nested controllers whenever it's necessary child controllers takes advantage of parent controllers attributes like in this type for BMWController.

Inheritance in Controllers

Inheritance will help when there was a some common logic which can be accessed over different controllers, we can implement that on BaseController. We can access that using $injector object that AngularJs Provides.

<!DOCTYPE html>
<html>

<head>
	<title> Simple App</title>
	<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>

<body>
	<div ng-app="" ng-controller="BMWController">
	
		My name is {{ name }} and I am a {{ type }}

		<button ng-click="clickme()">Click Me</button> 

	</div>
	
</body>

<script type="text/javascript">
	function CarController($scope) {
 
	$scope.name = 'Car';
	$scope.type = 'Car';
 
	$scope.clickme = function() {
		alert('This is parent controller "CarController" calling');
	}

}

function BMWController($scope, $injector) {
    
    $injector.invoke(CarController, this, {$scope: $scope});
    
    $scope.name = 'BMW';
 
}
</script>
</html>

                                                 

In the above example we defined two controllers called CarController and BMWController. CarController defines two attribute names called type on $scope and also defines one method clickme().

BMWController just overrides the name attribute and it doesn't have clickme method so it will use it from CarController and we do that using $inejctor.invoke() method. 

Single Page Application

Let us build a simple application which takes name, email and phone. It will be listed and gives options to edit and delete user details.

<!DOCTYPE html>
<html>

<head>
	<title> Simple App</title>
	<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>

<body>
	<div ng-app="" ng-controller="ContactController">
	    <form class="well">
	    <label>Name</label> 
	        <input type="text" name="name" ng-model="newcontact.name"/>
	    <label>Email</label> 
	        <input type="text" name="email" ng-model="newcontact.email"/>
	    <label>Phone</label> 
	        <input type="text" name="phone" ng-model="newcontact.phone"/>
	        <br/>
	        <input type="hidden" ng-model="newcontact.id" />
	     <input type="button" value="Save" ng-click="saveContact()" class="btn btn-primary"/>
	    </form>
		<table class="table table-striped table-bordered">
		<thead> 
		<tr>
		    <th>Name</th>
		    <th>Email</th>
		    <th>Phone</th>
		    <th>Action</th>
		</tr>
		</thead>
		<tbody>
		<tr ng-repeat="contact in contacts">
		    <td>{{ contact.name }}</td>
		    <td>{{ contact.email }}</td>
		    <td>{{ contact.phone }}</td>
		    <td>
		        <a  href="#" ng-click="edit(contact.id)">edit</a> | 
		        <a href="#" ng-click="delete(contact.id)">delete</a>
		    </td>
		 </tr>
		</tbody>
		</table>    
	</div>

	
</body>

<script type="text/javascript">
	var uid = 1;


function ContactController($scope) {
    
    $scope.contacts = [
        {id:0, 'name': 'Viral', 'email':'hello@gmail.com', 'phone': '123-2343-44'}
    ];
    
    $scope.saveContact = function() {
        
        if($scope.newcontact.id == null) {
             $scope.newcontact.id = uid++;
             $scope.contacts.push($scope.newcontact);
        } else {
            
             for(i in $scope.contacts) {
                    if($scope.contacts[i].id == $scope.newcontact.id) {
                        $scope.contacts[i] = $scope.newcontact;
                    }
             }                
        }
        $scope.newcontact = {};
    }

    
    $scope.delete = function(id) {
        
        for(i in $scope.contacts) {
            if($scope.contacts[i].id == id) {
                $scope.contacts.splice(i,1);
                $scope.newcontact = {};
            }
        }
        
    }
    
    
    $scope.edit = function(id) {
        for(i in $scope.contacts) {
            if($scope.contacts[i].id == id) {
                $scope.newcontact = angular.copy($scope.contacts[i]);
            }
        }
    }
}
</script>
</html>

We created a form which will take email, name and phone inputs on click of Save button. On click of Save button it will call saveContact function on $scope object. It will add new contact to the present existing array of contacts. In the first step we are initializing a variable called uid which will taken care of the $scope contacts array initialization by default.

We saw how to create controllers and use $scope object to bind model values with the views. We went through angularjs attributes called ng-controller, ng-repeat and ng-click. Also we saw how to create controllers within Modules, nested controllers and inheritance controllers. 

Finally we created a small application using what we learnt.

Thanks

Kode Info

Author

  • Imran Iqbal
    Imran Iqbal

    Imran is a web developer and consultant from India. He is the founder of KodeInfo, the PHP and Laravel Community . In the meantime he follows other projects, works as a freelance backend consultant for PHP applications and studies IT Engineering . He loves to learn new things, not only about PHP or development but everything.

Related

WHY USE A FRAMEWORK OVER PLAIN PHP

WHY USE A FRAMEWORK OVER PLAIN PHP
read more

GETTING STARTED WITH LARAVEL

GETTING STARTED WITH LARAVEL
read more

UNDERSTANDING LARAVEL STRUCTURE

UNDERSTANDING LARAVEL STRUCTURE
read more

UNDERSTANDING LARAVEL ROUTES

UNDERSTANDING LARAVEL ROUTES
read more

comments powered by Disqus