admin管理员组文章数量:1130214
I have a basic controller that displays my products,
App.controller('ProductCtrl',function($scope,$productFactory){
$productFactory.get().success(function(data){
$scope.products = data;
});
});
In my view I'm displaying this products in a list
<ul>
<li ng-repeat="product as products">
{{product.name}}
</li>
</ul
What I'm trying to do is when someone click on the product name, i have another view named cart where this product is added.
<ul class="cart">
<li>
//click one added here
</li>
<li>
//click two added here
</li>
</ul>
So my doubt here is, how do pass this clicked products from first controller to second? i assumed that cart should be a controller too.
I handle click event using directive. Also i feel i should be using service to achieve above functionality just can't figure how? because cart will be predefined number of products added could be 5/10 depending on which page user is. So i would like to keep this generic.
Update:
I created a service to broadcast and in the second controller i receive it. Now the query is how do i update dom? Since my list to drop product is pretty hardcoded.
I have a basic controller that displays my products,
App.controller('ProductCtrl',function($scope,$productFactory){
$productFactory.get().success(function(data){
$scope.products = data;
});
});
In my view I'm displaying this products in a list
<ul>
<li ng-repeat="product as products">
{{product.name}}
</li>
</ul
What I'm trying to do is when someone click on the product name, i have another view named cart where this product is added.
<ul class="cart">
<li>
//click one added here
</li>
<li>
//click two added here
</li>
</ul>
So my doubt here is, how do pass this clicked products from first controller to second? i assumed that cart should be a controller too.
I handle click event using directive. Also i feel i should be using service to achieve above functionality just can't figure how? because cart will be predefined number of products added could be 5/10 depending on which page user is. So i would like to keep this generic.
Update:
I created a service to broadcast and in the second controller i receive it. Now the query is how do i update dom? Since my list to drop product is pretty hardcoded.
Share Improve this question edited Nov 24, 2013 at 23:00 kishanio asked Nov 24, 2013 at 21:35 kishaniokishanio 7,0798 gold badges26 silver badges33 bronze badges 1- 1 Possible duplicate of Pass variables to AngularJS controller, best practice? – T.Todua Commented Sep 20, 2016 at 11:29
18 Answers
Reset to default 326From the description, seems as though you should be using a service. Check out http://egghead.io/lessons/angularjs-sharing-data-between-controllers and AngularJS Service Passing Data Between Controllers to see some examples.
You could define your product service (as a factory) as such:
app.factory('productService', function() {
var productList = [];
var addProduct = function(newObj) {
productList.push(newObj);
};
var getProducts = function(){
return productList;
};
return {
addProduct: addProduct,
getProducts: getProducts
};
});
Dependency inject the service into both controllers.
In your ProductController
, define some action that adds the selected object to the array:
app.controller('ProductController', function($scope, productService) {
$scope.callToAddToProductList = function(currObj){
productService.addProduct(currObj);
};
});
In your CartController
, get the products from the service:
app.controller('CartController', function($scope, productService) {
$scope.products = productService.getProducts();
});
how do pass this clicked products from first controller to second?
On click you can call method that invokes broadcast:
$rootScope.$broadcast('SOME_TAG', 'your value');
and the second controller will listen on this tag like:
$scope.$on('SOME_TAG', function(response) {
// ....
})
Since we can't inject $scope into services, there is nothing like a singleton $scope.
But we can inject $rootScope
. So if you store value into the Service, you can run $rootScope.$broadcast('SOME_TAG', 'your value');
in the Service body. (See @Charx description about services)
app.service('productService', function($rootScope) {/*....*/}
Please check good article about $broadcast, $emit
Solution without creating Service, using $rootScope:
To share properties across app Controllers you can use Angular $rootScope. This is another option to share data, putting it so that people know about it.
The preferred way to share some functionality across Controllers is Services, to read or change a global property you can use $rootscope.
var app = angular.module('mymodule',[]);
app.controller('Ctrl1', ['$scope','$rootScope',
function($scope, $rootScope) {
$rootScope.showBanner = true;
}]);
app.controller('Ctrl2', ['$scope','$rootScope',
function($scope, $rootScope) {
$rootScope.showBanner = false;
}]);
Using $rootScope in a template (Access properties with $root):
<div ng-controller="Ctrl1">
<div class="banner" ng-show="$root.showBanner"> </div>
</div>
You can do this by two methods.
By using
$rootscope
, but I don't reccommend this. The$rootScope
is the top-most scope. An app can have only one$rootScope
which will be shared among all the components of an app. Hence it acts like a global variable.Using services. You can do this by sharing a service between two controllers. Code for service may look like this:
app.service('shareDataService', function() { var myList = []; var addList = function(newObj) { myList.push(newObj); } var getList = function(){ return myList; } return { addList: addList, getList: getList }; });
You can see my fiddle here.
An even simpler way to share the data between controllers is using nested data structures. Instead of, for example
$scope.customer = {};
we can use
$scope.data = { customer: {} };
The data
property will be inherited from parent scope so we can overwrite its fields, keeping the access from other controllers.
angular.module('testAppControllers', [])
.controller('ctrlOne', function ($scope) {
$scope.$broadcast('test');
})
.controller('ctrlTwo', function ($scope) {
$scope.$on('test', function() {
});
});
I saw the answers here, and it is answering the question of sharing data between controllers, but what should I do if I want one controller to notify the other about the fact that the data has been changed (without using broadcast)? EASY! Just using the famous visitor pattern:
myApp.service('myService', function() {
var visitors = [];
var registerVisitor = function (visitor) {
visitors.push(visitor);
}
var notifyAll = function() {
for (var index = 0; index < visitors.length; ++index)
visitors[index].visit();
}
var myData = ["some", "list", "of", "data"];
var setData = function (newData) {
myData = newData;
notifyAll();
}
var getData = function () {
return myData;
}
return {
registerVisitor: registerVisitor,
setData: setData,
getData: getData
};
}
myApp.controller('firstController', ['$scope', 'myService',
function firstController($scope, myService) {
var setData = function (data) {
myService.setData(data);
}
}
]);
myApp.controller('secondController', ['$scope', 'myService',
function secondController($scope, myService) {
myService.registerVisitor(this);
this.visit = function () {
$scope.data = myService.getData();
}
$scope.data = myService.getData();
}
]);
In this simple manner, one controller can update another controller that some data has been updated.
we can store data in session and can use it anywhere in out program.
$window.sessionStorage.setItem("Mydata",data);
Other place
$scope.data = $window.sessionStorage.getItem("Mydata");
1
using $localStorage
app.controller('ProductController', function($scope, $localStorage) {
$scope.setSelectedProduct = function(selectedObj){
$localStorage.selectedObj= selectedObj;
};
});
app.controller('CartController', function($scope,$localStorage) {
$scope.selectedProducts = $localStorage.selectedObj;
$localStorage.$reset();//to remove
});
2
On click you can call method that invokes broadcast:
$rootScope.$broadcast('SOME_TAG', 'your value');
and the second controller will listen on this tag like:
$scope.$on('SOME_TAG', function(response) {
// ....
})
3
using $rootScope:
4
window.sessionStorage.setItem("Mydata",data);
$scope.data = $window.sessionStorage.getItem("Mydata");
5
One way using angular service:
var app = angular.module("home", []);
app.controller('one', function($scope, ser1){
$scope.inputText = ser1;
});
app.controller('two',function($scope, ser1){
$scope.inputTextTwo = ser1;
});
app.factory('ser1', function(){
return {o: ''};
});
I've created a factory that controls shared scope between route path's pattern, so you can maintain the shared data just when users are navigating in the same route parent path.
.controller('CadastroController', ['$scope', 'RouteSharedScope',
function($scope, routeSharedScope) {
var customerScope = routeSharedScope.scopeFor('/Customer');
//var indexScope = routeSharedScope.scopeFor('/');
}
])
So, if the user goes to another route path, for example '/Support', the shared data for path '/Customer' will be automatically destroyed. But, if instead of this the user goes to 'child' paths, like '/Customer/1' or '/Customer/list' the the scope won't be destroyed.
You can see an sample here: http://plnkr.co/edit/OL8of9
I don't know if it will help anyone, but based on Charx (thanks!) answer I have created simple cache service. Feel free to use, remix and share:
angular.service('cache', function() {
var _cache, _store, _get, _set, _clear;
_cache = {};
_store = function(data) {
angular.merge(_cache, data);
};
_set = function(data) {
_cache = angular.extend({}, data);
};
_get = function(key) {
if(key == null) {
return _cache;
} else {
return _cache[key];
}
};
_clear = function() {
_cache = {};
};
return {
get: _get,
set: _set,
store: _store,
clear: _clear
};
});
Make a factory in your module and add a reference of the factory in controller and use its variables in the controller and now get the value of data in another controller by adding reference where ever you want
One way using angular service:
var app = angular.module("home", []);
app.controller('one', function($scope, ser1){
$scope.inputText = ser1;
});
app.controller('two',function($scope, ser1){
$scope.inputTextTwo = ser1;
});
app.factory('ser1', function(){
return {o: ''};
});
<div ng-app='home'>
<div ng-controller='one'>
Type in text:
<input type='text' ng-model="inputText.o"/>
</div>
<br />
<div ng-controller='two'>
Type in text:
<input type='text' ng-model="inputTextTwo.o"/>
</div>
</div>
https://jsfiddle.net/1w64222q/
FYI The $scope Object has the $emit, $broadcast, $on AND The $rootScope Object has the identical $emit, $broadcast, $on
read more about publish/subscribe design pattern in angular here
To improve the solution proposed by @Maxim using $broadcast, send data don't change
$rootScope.$broadcast('SOME_TAG', 'my variable');
but to listening data
$scope.$on('SOME_TAG', function(event, args) {
console.log("My variable is", args);// args is value of your variable
})
There are three ways to do it,
a) using a service
b) Exploiting depending parent/child relation between controller scopes.
c) In Angular 2.0 "As" keyword will be pass the data from one controller to another.
For more information with example, Please check the below link:
http://www.tutorial-points.com/2016/03/angular-js.html
var custApp = angular.module("custApp", [])
.controller('FirstController', FirstController)
.controller('SecondController',SecondController)
.service('sharedData', SharedData);
FirstController.$inject = ['sharedData'];
function FirstController(sharedData) {
this.data = sharedData.data;
}
SecondController.$inject['sharedData'];
function SecondController(sharedData) {
this.data = sharedData.data;
}
function SharedData() {
this.data = {
value: 'default Value'
}
}
First Controller
<div ng-controller="FirstController as vm">
<input type=text ng-model="vm.data.value" />
</div>
Second Controller
<div ng-controller="SecondController as vm">
Second Controller<br>
{{vm.data.value}}
</div>
I think the
best way
is to use $localStorage. (Works all the time)app.controller('ProductController', function($scope, $localStorage) {
$scope.setSelectedProduct = function(selectedObj){
$localStorage.selectedObj= selectedObj;
};
});
Your cardController will be
app.controller('CartController', function($scope,$localStorage) {
$scope.selectedProducts = $localStorage.selectedObj;
$localStorage.$reset();//to remove
});
You can also add
if($localStorage.selectedObj){
$scope.selectedProducts = $localStorage.selectedObj;
}else{
//redirect to select product using $location.url('/select-product')
}
本文标签: javascriptPassing data between controllers in Angular JSStack Overflow
版权声明:本文标题:javascript - Passing data between controllers in Angular JS? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736710035a1948890.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论