Sharing Data across Angular.js Controllers

Posted by: Mahesh Sabnis , on 4/6/2016, in Category AngularJS
Views: 20247
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.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Mahesh Sabnis is a DotNetCurry author and a Microsoft MVP having over two decades 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), and Front-end technologies like Angular and React. Follow him on twitter @maheshdotnet or connect with him on LinkedIn


Page copy protected against web site content infringement 	by Copyscape




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