DotNetCurry Logo

Sharing Data across Angular.js Controllers

Posted by: Mahesh Sabnis , on 4/6/2016, in Category AngularJS
Views: 9473
Abstract: Sharing data across Angularjs controllers using Angular Factory object

Angular.js is commonly related to Single Page Applications (SPA). In SPA applications, we have several Views loaded in one master page (you can call it as an Index page) in which case, we have one or more controllers bound with one View. When we navigate from one view to another, we may want to pass data across views using one controller to another.

To pass or share data across controllers, we need to make use of the Angular Factory object.

 

Angular Factory

This is an Angular component which can be injected in another component e.g. Controller, Service, etc. Using factory, we have the freedom to decide what to instantiate and what is returned from the factory. Using the factory, we can share same object across controllers.

Angular.js application Implementation

This application is implemented using Visual Studio 2015 but it can also be implemented using any other IDE like SublimeText, Visual Studio 2013, Visual Studio Code (VSCode) etc.

Step 1: Open Visual Studio and create a new Empty Application, name it as NG_SharingDataAcrossControllers. In this project, right click and using Manage NuGet Packages, install AngularJS as shown in the following image

angulajs-core

This will create a Scripts folder in the project with angular scripts in it.

Step 2: In the project, add a new folder of name app. In this folder, add a MyScripts and Views folder.

Step 3: At the project root level, add a new html page of name Index.html and a JavaScript file of name module.js. In the Views folder, add an html page of the name List.html and Details.html. In the MyScripts folder, add listcontroller.js and details.js.

Add the following code in module.js

//1.
var app = angular.module('main', ['ngRoute']);
//2.
app.factory('fact', function () {
    return {
        data: {}
    }
});
//3.
app.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
    $routeProvider.when("/", {
        templateUrl: 'app/Views/List.html',
        controller: 'listctrl'
    });
    $routeProvider.when("/details", {
        templateUrl: 'app/Views/Details.html',
        controller: 'detailsctrl'
    });
    $routeProvider.otherwise("/");
}]);

The above code have following specifications:

(Note: The following line numbers matches with the comments applied in the code.)

1. The angular module definition has dependency on ngRoute and is used for implementing routing.

2. This is an important part of the code. This is the Angular factory and returns the JavaScript object of name data.

3. The Angular configuration function which initializes and loads all the dependency providers. In our case, we are using $routeProvider and $locationProvider. These are used for defining routing. The routes are defined for List view and Details views with their respective controllers listctrl and detailsctrl.

Add the following code in listcontroller.js

//1.
app.controller('listctrl', function ($scope, fact, $location) {
  
    $scope.Employees = [
        { EmpNo: 101, EmpName: 'MS', Salary: 23000 },
        { EmpNo: 102, EmpName: 'LS', Salary: 13000 },
        { EmpNo: 103, EmpName: 'TS', Salary: 3000 },
        { EmpNo: 104, EmpName: 'VB', Salary: 43000 },
        { EmpNo: 105, EmpName: 'PB', Salary: 33000 },
        { EmpNo: 106, EmpName: 'AB', Salary: 13000 }
    ];

    $scope.getSelected = function (emp) {
       fact.Data = emp;
        $location.path("/details");
    };
});

This piece of code declares an Angular controller of name listctrl. This is passed with dependency of Angular factory fact and $location. This controller defines Employees array containing Employee details. The getSelected() function accepts an emp input parameter which is assigned to the data object returned by the angular factory fact. This function calls the path() function of the $location object. This function is passed with the route expression /details which is defined in the Angular configuration.

 

In the detailscontroller.js, add the following code

//1.
app.controller('detailsctrl', function ($scope, fact, $location) {
   
    $scope.Employee = {
        EmpNo: fact.Data.EmpNo,
        EmpName: fact.Data.EmpName,
        Salary: fact.Data.Salary
    };
    $scope.back = function () {
        $location.path("/");
    }
});

The above code defines an Angular controller of name detailsctrl. This is passed with the dependency on angular factory of name fact and the $location object. This defines Employee object which is initialized with the values received from angular factory. The back() function calls the path() function of $location object. This has input parameter ‘/’ which is a route expression defined in the Angular configuration which will navigate to the List.html.

The listctrl and detailsctrl are passed with the Angular factory as dependencies. The factory object returns an instance of data object which contains values passed across controllers.

Add following markup in Index.html

<!DOCTYPE html>
<html ng-app="main">
<head>
    <title></title>
    <meta charset="utf-8" />

    <link href="Content/bootstrap.min.css" rel="stylesheet" />
    http://Scripts/jquery-2.2.0.min.js
    http://Scripts/bootstrap.min.js
    http://Scripts/angular.min.js
    http://Scripts/angular-route.min.js
    http://module.js
    http://app/MyScripts/listcontroller.js
    http://app/MyScripts/detailscontroller.js

</head>`
<body>
    <h1>Sharing Data Acorss Controllers</h1>
    <h2>The Index View</h2>

 
    
 
</body> </html>

The above index view loads the angular module app. This uses ng-view which will be used to navigate across views. The index.html loads all script files.

Add following markup in List.html

EmpNo EmpName Salary  
{{Emp.EmpNo}} {{Emp.EmpName}} {{Emp.Salary}} details

This view is bound with the listctrl and all its scope declarations. This generates html table based on the Employees array, the table contains anchor tag which is bound with the getSelected() function.

Add the following markup in Details.html

EmpNo {{Employee.EmpNo}}
EmpName {{Employee.EmpName}}
Salary {{Employee.Salary}}
Go Back

This view is bound with detailsctrl and contains table bound with the scopes declared in the controller.

Run the Index.html and the following result will be displayed

index-with-list

Click on details for a row in the table, the selected row will be displayed in the Details view as shown in the following image

details-view

If you click on the Go Back link, the List page will be displayed.

Conclusion

Using Angular Factory, we can easily share data across Angular controllers.

Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+
Further Reading - Articles You May Like!
Author
Mahesh Sabnis is a DotNetCurry author and Microsoft MVP having over 17 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). Follow him on twitter @maheshdotnet


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!