How to share data between controllers in AngularJS

We often need data that we want to share throughout the application, just like global variable but JavaScript discourages global variables so, what if one part of application needs data from another part of application, in angular we can share data between controllers using services, let's see an example which demonstrates how to share data between controllers in angular.

Understanding the concept of service in AngularJS

In AngularJS you will find yourself repeating some code across the controllers, it may be ajax calls or some other type of related code. services are great way to refactor our code  that can be shared across the controllers, factories and services are directly built into AngularJS and they make it really easy to provide a single place to go all of our reusable code.

Benefits of services

  • Services are the best place to put reusable code like API calls which multiple controllers can use.
  • Services makes our code organized which leads us to clean code that is easier to maintain.
  • Services are singleton objects so they are much more memory efficient. 

Creating Services

There are five ways to create a service-

  1. provider()
  2. factory()
  3. service()
  4. value()
  5. constant()

Note : I will be using non array syntax which will break when we minify our code, head here to see how to make your code minification proof

provider()

All of other functions except constant is just wrappers around provider(), so it is good idea to know how to create service using provider() function.

<div ng-controller="BooksController as books">
	<ul>
		<li ng-repeat="book in books.books">{{ book.name }} by - {{ book.publisher }}</li>
	</ul>
</div>
	
var app = angular.module('app', []);

app.provider('books', function() {

    this.$get = function( ) {
        var books =  [
        {
            id : 1,
            name : "book1",
            publisher : "publisher1"
        },
        {
            id : 2,
            name : "book2",
            publisher : "publisher2"
        }
        ]

        return {
            getBooks : books
        }

    }
});


app.controller('BooksController', function( books ) {
    var vm = this;

    vm.books = books.getBooks;

});

Note: you need to create $get function, $get will be executed to create our service and what's returned from $get can be accessed by controllers.

Provider function is also useful when you need little bit more configuration and control over your service.

factory()

factory is the very popular way to create service in angular, if you don't need to configure the provider then using a factory function is simpler and more readable to create services.

<div ng-controller="BooksController as books">
    <ul>
        <li ng-repeat="book in books.books">{{ book.name }} by - {{ book.publisher }}</li>
    </ul>
</div>
var app = angular.module('app', []);

app.factory('books', function() {
    var books =  [
        {
            id : 1,
            name : "book1",
            publisher : "publisher1"
        },
        {
            id : 2,
            name : "book2",
            publisher : "publisher2"
        }
    ]

    return {
        getBooks : books
    }
});


app.controller('BooksController', function( books ) {
    var vm = this;

    vm.books = books.getBooks;

}) 

service()

Service is another popular way to create services, it's just wrapper around the factory function.

<div ng-controller="BooksController as books">
	<ul>
		<li ng-repeat="book in books.books">{{ book.name }} by - {{ book.publisher }}</li>
	</ul>
</div>
var app = angular.module('app', []);

app.service('bookService', function() {
	var books =  [
	{
		id : 1,
		name : "book1",
		publisher : "publisher1"
	},
	{
		id : 2,
		name : "book2",
		publisher : "publisher2"
	}
	];
	this.getAllBooks = function() {
		return books;
	}
});


app.controller('BooksController', function( bookService ) {
	var vm = this;

	vm.books = bookService.getAllBooks();
	console.log(vm.books);

});

Note: difference between factory and service is that the function we pass to service method will be treated as constructor and called with new operator.

value() and constant()

value is just a wrapper around factory, you can use value instead of factory if you don't need to inject anything into the service.

constant is a type of service where you put values that won't change, it can be function or string.

<div ng-controller="BooksController as books">
	<h1>{{ books.appname }} {{ books.version}}</h1>
	<ul>
		<li ng-repeat="book in books.books">{{ book.name }} by - {{ book.publisher }}</li>
	</ul>
</div>
var app = angular.module('app', []);
app.constant('constants', {
	APP_NAME : 'Book Store',
	APP_VERSION : '1.0'
});

app.value('bookService', {
	getAllBooks : function() {
		return [
			{
				id : 1,
				name : "book1",
				publisher : "publisher1"
			},
			{
				id : 2,
				name : "book2",
				publisher : "publisher2"
			}
		];
	}
});
app.controller('BooksController', function( bookService, constants ) {
	var vm = this;

	vm.books = bookService.getAllBooks();
	vm.appname = constants.APP_NAME;
	vm.version = constants.APP_VERSION;

})

Let's understand the concept with simple example

In this example we are going to create an app that displays all the books with their author name, it also displays each author with books written by them, it seems we need to share data between two controllers let's see how can we do it.

I am going to create two service authorService which returns the array of authors, and bookService which contains two functions getAllbooks and getBooksByAuthor.

<div ng-controller="BooksController as books">
	<h1>All Books</h1>
	<ul>
		<li ng-repeat="book in books.books">{{ book.name }} by - {{ book.author }}</li>
	</ul>
</div>

<div ng-controller="AuthorController as author">
	<h1>Books by Authors</h1>
	<ul>
		<li ng-repeat="authorname in author.authors">
			<strong>{{ authorname }} : </strong>
			<span ng-repeat="books in author.booksByAuthor(authorname)">{{ books.name}}, </span> 
		</li>
	</ul>
</div>
var app = angular.module('app', []);

app.service('bookService', function() {
	var books =  [
		{ id : 1, name : "book1", author : "author1" },
		{ id : 2, name : "book2", author : "author2" },
		{ id : 3, name : "book3", author : "author1" },
		{ id : 4, name : "book4", author : "author1" },
		{ id : 5, name : "book5", author : "author2" },
		{ id : 6, name : "book6", author : "author3" },

	];
	this.getAllBooks = function() {
		return books;
	};

	this.getBooksByAuthor = function(authorname) {
		var result = [];
		result = books.filter(function(element) {
			return element.author == authorname;
		});
		return result;
	}
});

app.service('authorService', function() {
	this.getAllAuthors = function() {
		return [
			'author1',
			'author2',
			'author3'
		]
	}
})

app.controller('AuthorController', function(bookService, authorService) {
	var vm = this;
	vm.authors = authorService.getAllAuthors();

	vm.booksByAuthor = function(authorname) {
		return bookService.getBooksByAuthor(authorname);
	}
})

app.controller('BooksController', function( bookService ) {
	var vm = this;
	vm.books = bookService.getAllBooks();

})

Conclusion

Services are great way to share data all over the application, they are singleton objects that stays in mamory and can be resused, so it is good idea to put your code such as api calls in service.

If you have any question, Post thread in our forum and I will try my best to to answer your queries, anyways if you have something to say, please tell us in comment section below.

Something to say? Tell us in comment section.