AngularJS: How can I share data across controller? - angularjs

I want to get title dynamically. How do I share the $scope.title in indexCtrl?
var app = angular.module('app', []);
app.controller('firstCtrl', function($scope){
$scope.title = 'OneFC';
})
app.controller('secondCtrl', function($scope){
$scope.title = 'UFC';
})
app.controller('indexCtrl', function(){
// i want to get the title here depends on the active state in ui-router.
}

We have some ways to do this. rootscope's property can handle this which is same as global var in your app. But I love OOP and I think we should encapsulate the processing of data in a service.
Code for service:
app.factory('titleFactory',function(){
var _title = null;
return {
setTitle: function(title) {
this._title = title;
},
getTitle: function() {
return this._title;
}
}
});
Now in any controller you just need inject and call get or set title to handle your data.
Set title value (same for secondCtrl):
app.controller('firstCtrl', function($scope,titleFactory){
titleFactory.setTitle('OneFC');
})
Title now can be accessed by all other controllers like this:
app.controller('indexCtrl', function(){
$scope.title = titleFactory.getTitle();
});

I would recomend passing it as Data inside your routes definitions (you can do that in case you were not aware of) just like this:
$stateProvider.state("page1", {
url: "/page1",
data: {
title: "Your Title Here"
},
views: {
}
}).state("page2", {
url: "/page2",
data: {
title: "Your Other Title Here"
},
views: {
}
})
Afterwards, you can use it in your controller like this:
app.controller('indexCtrl', function($state){ //Note that you inject state
$scope.pageTitle= $state.data.title;
}
Hope this works for you
Regards

try to use $rootScope.title?
app.controller('indexCtrl', ['$rootScope','$scope',function($rootScope, $scope){
$rootScope.$on("toindexCtrl", function (e) {
$scope.$apply(function () {
$scope.title = $rootScope.title;
});
});
}])
app.controller('secondCtrl', ['$rootScope','$scope', function($rootScope, $scope){
$rootScope.title = 'UFC';
$rootScope.$broadcast('toindexCtrl');
}])
This code work for me. I also use $broadcast to listen when the value changed.

Related

pass the value from one page to another using rootscope in angularJS

Login.js:
app.controller('LoginFormController', ['$scope','$http','$rootScope', '$state', function($scope, $http, $rootScope, $state) {
$scope.user = {};
$scope.authError = null;
$scope.login = function() {
$scope.authError = null;
var emailId = $scope.user.email;
var password = $scope.user.password;
$http({
url: 'http://localhost:8090/login/login',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: 'email='+emailId+'&password='+password
//data: {'email': $scope.user.email, 'password': $scope.user.password}
}).then(function(response) {
console.log(response.data);
if (response.data.status == 'SUCCESS') {
$scope.user = response.data.user.firstName;
$rootScope.test = response.data.user.firstName;
console.log("check: ",$rootScope.test)
$state.go('app.dashboard');
} else {
//alert('invalid login');
$scope.authError = 'Email or Password not right';
}
}, function(x) {
$scope.authError = 'Server Error';
})
};
}])
I saved the value under $rootScope.test
Here Is my App.main.js:
'use strict';
angular.module('app').controller('AppCtrl', ['$scope','$rootScope',
function($scope, $rootScope) {
$scope.user5 = $rootScope.test;
}
]);
trying to print the rootscope
If I run this Code i am facing the error of $rootScope is undefined in the console. How to Resolve this
$rootScope is the parent of all $scope, each $scope receives a copy of $rootScope data which you can access using $scope itself.
Here is a modified version
https://jsfiddle.net/sedhal/g08uecv5/17/
angular.module('myApp', [])
.run(function($rootScope) {
$rootScope.obj = {
"name":"user1",
"bdate":"18/11/1994",
"city":"Ahmedabad"
};
})
.controller('myCtrl', function($scope, $rootScope) {
$scope.data = $rootScope.obj;
})
.controller('myCtrl2', function($scope, $rootScope) {
$scope.data1 = $rootScope.obj;
});
There is a useful answer to your question here: https://stackoverflow.com/a/18881189/9013688
Instead of passing directly your property on the $rootScope, you could emit an event which could be listened in an other part of your app like this:
if (response.data.status == 'SUCCESS') {
$rootScope.$emit('user-logged', response.data.user.firstName)
}
And then:
$rootScope.$on('user-logged', function(event, data){
do something with your data
})
Or you could use a service which is a good way to handle your data in all your app.
Please ensure that you take the advice of georgeawg, his suggestion seems to be the best way to implement this functionality in my opinion.
I want to suggest what might be wrong with your example.
If you can see that in the main App.main.js you have given the declaration as
angular.module('app').controller(...
But you are using a variable app in login.js like so.
app.controller(...
Which I am assuming you are creating somewhere else. Thus the set rootscope value is lost because there are two instances of the same app.
The solution to your problem will be to declare one variable app which will store the instance of the app. So the fix for your solution will be to modify App.main.js to be like so.
var app = angular.module('app');
app.controller(...
Also you need to remove any other arbitary var app = in your complete code, since these will create multiple instances of the same app.
I hope my explanation was understandable and the correct guess, please try out this solution!
In your main js add this.
app.run(['$rootScope', function($rootScope) {
$rootScope.test;
}]);
Here is a sample implementation of george's suggestion which is the proper way to handle this.
app.controller('LoginFormController', ['$scope','$http','$rootScope', '$state', 'stateService', function($scope, $http, $rootScope, $state, stateService) {
var userFirstName = 'John';
stateService.setFirstName('Bill');
userFirstName = stateService.getFirstName();
console.log(userFirstName); // result will be 'Bill'
}])
And the service which I usually call stateService
app.factory('stateService', [factory]);
function factory() {
var userFirstName = null;
stateService.getFirstName = function() {
return userFirstName;
};
stateService.setFirstName = function(firstName) {
userFirstName = firstName;
};
return stateService;
}

how to inject factory to controller

I am calling a function in a factory and trying to inject in the controller. But I am getting an error saying, unknown provider. Please let me know where I am going wrong.
app.factory('pdfdwn', function($scope) {
return{
download:function(){
html2canvas(document.getElementById('export'), {
onrendered: function (canvas) {
var data = canvas.toDataURL();
var docDefinition = {
content: [{
image: data,
width: 500,
}]
};
pdfMake.createPdf(docDefinition).download("Table.pdf");
}
});
return download();
}
}
});
controller:
app.controller('myctrl', function($scope,pdfdwn){
$scope.pdf = function() {
var pdd = pdfdwn.download();
};
});
1.remove $scope from factory method because you cannot inject inside.
2.Remove the return download(); from the factory, because u are already returning the download.
Inside the controller:
app.controller('myctrl', function($scope,pdfdwn){
$scope.pdf = function() {
pdfdwn.download();
};
});

Issues updating angular view from another controller

In the below, I have a sidenav and a main content section. I am trying to call the sidenav function from the main controller so the number updtes in the sidenav. What am I doing wrong here?
This is my view.
<div>Teams {{ teams.length }} </div>
This is my sidebar controller:
angular.module('myApp').controller('leftNav', function($scope, myFactory) {
myFactory.getTeams().then(function(res) {
$scope.teams = res.data;
})
This is my factory
angular.module('myApp').factory('myFactory', function($http) {
return {
getTeams : function() {
return $http.get('/teams').then(function(res) {
return res;
});
}
};
});
This is a complete different controller:
angular.module('myApp').controller('main', function($scope,$http, myFactory) {
$http.post(...blablabl..).then(function() {
// What can i call here to update the sidenav above?
});
});
You can utilise $controller service to call your leftNav controller from your main controller like below
angular.module('myApp').controller('main', function($scope,$http, myFactory,$controller) {
$http.post(...blablabl..).then(function() {
var leftCTRL= $controller('leftNav', { $scope: $scope.$new() });
});
});
you can try like so :
angular.module('myApp').controller('leftNav', function($scope, myFactory) {
myFactory.getTeams().then(function(res) {
this.teams = res.data;
})
angular.module('myApp').controller('main', function($scope,$http, $controller) {
var leftNav= $controller('leftNav');
$http.post(...blablabl..).then(function(res) {
leftNav.teams = res.data;
});
});

Ionic: Passing array elements between controllers

I have a controller & view which computes and displays a specific element. When I click a button on the view, I want to open another which shows more information about the item.
What is the best way to pass the element to another controller for display?
Many thanks
You could build a service which get data from one controller and passing it to the other, like so:
.factory('shareData', function(){
var finalData;
return {
sendData: function(data) {
finalData = data;
},
getData: function() {
return finalData;
}
}
});
Another option you have is to create a shared varraible in your main controller('app' controller in ionic)
.controller('app', function($scope){
$scope.data;
})
.controller('app.controller1', function($scope){
$scope.data = "Hello World";
})
.controller('app.controller2', function($scope){
console.log($scope.data); //Hello World
});
Yet another option besides those included by Matan Gubkin is including the array in the $rootScope: this way you will be able to access it from everywhere.
#Matan Gubkin idea is close, but you should use the service to get the specific item that you desire.
.factory('shareData', function(){
var finalData = ["Hello World",'more data'];
return {
sendData: function(data) {
finalData = data;
},
getData: function() {
return finalData;
},
getItem:function(_id) {
return finalData[_id];
}
}
});
then in setting up your controllers
.controller('app.controller', function($scope){
})
.controller('app.controller-list', function($scope,shareData){
$scope.data = shareData.getData();
})
.controller('app.controller-detail', function($scope,$stateParams,shareData){
// use stateParams to get index
console.log(shareData.getItem($stateParams.index)); //
});
setting up your routes
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: "/app",
abstract: true,
controller: 'app.controller'
})
.state('app.controller-list', {
url: "/list",
})
.state('app.controller-detail', {
url: "/detail/:index", // <-- pass in index as stateParam
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/list');
});

AngularJS, ngResource, Service and multiple controllers. How to keep data synchronized?

I searched a lot about this, and although I found some similar problems, they are not exactly what I want.
Imagine this kind of code:
angular
.module('foobar', ['ngResource'])
.service('Brand', ['$resource', function($resource){
return $resource('/api/v1/brands/:id', { id: '#id' });
}])
.service('Product', ['$resource', function($resource){
return $resource('/api/v1/products/:id', { id: '#id' });
}])
.controller('ProductController', ['$scope', 'Brand', function($scope, Brand){
$scope.brands = Brand.query();
}])
.controller('BrandController', ['$scope', 'Brand', function($scope, Brand){
this.create = function() {
Brand.save({label: $scope.label });
};
}])
For the moment, I'm using $broadcast and $on
In brand controller:
Brand.save({label: $scope.label }, function(brand){
$rootScope.$broadcast('brand-created', brand);
});
In product controller:
$scope.$on('brand-created', function(brand){
$scope.brands.push(brand);
});
It works, but I don't like this way of sync'ing datas.
Imagine you have 10 controllers which must be sync'ed, you should write the $scope.$on part in each. And do the save for each services...
Is there a better way to keep collection sync'ed wherever they are used?
Yes - using a shared service. I've used http in my example, but you could fairly easily substitute it with $resource. The main point over here is to keep an in memory copy of the list of the brands. This copy is referred by the productscontroller and whenever it is updated it will automatically reflect. You simply need to ensure that you update it correctly after making the $http put / resource put call.
http://plnkr.co/edit/k6rwS0?p=preview
angular.module('foobar', [])
.service('Brand', ['$http', '$q',
function($http, $q) {
var brandsList;
return {
getBrands: function() {
var deferred = $q.defer();
//if we have not fetched any brands yet, then we'll get them from the api
if (!brandsList) {
$http.get('brands.json').then(function(response) {
brandsList = response.data;
console.log('brands:' + brandsList);
deferred.resolve(brandsList);
});
} else {
deferred.resolve(brandsList);
}
return deferred.promise;
},
save: function(newBrand) {
// $http.put('brands.json', newBrand).then(function(){
// //update the list here on success
// brandsList.push(newBrand)
// })
brandsList.push({
name: newBrand
});
}
};
}])
.controller('productsController', ['$scope', 'Brand',
function($scope, Brand) {
Brand.getBrands().then(function(brands) {
$scope.brands = brands;
})
}
])
.controller('brandsController', ['$scope', 'Brand',
function($scope, Brand) {
$scope.create = function() {
Brand.save($scope.label);
};
}
])

Resources