[英]Share data between AngularJS controllers
我正在嘗試跨控制器共享數據。 用例是一種多步驟形式,在一個輸入中輸入的數據稍后用於原始控制器之外的多個顯示位置。 下面的代碼和這里的 jsfiddle代碼。
HTML
<div ng-controller="FirstCtrl">
<input type="text" ng-model="FirstName"><!-- Input entered here -->
<br>Input is : <strong>{{FirstName}}</strong><!-- Successfully updates here -->
</div>
<hr>
<div ng-controller="SecondCtrl">
Input should also be here: {{FirstName}}<!-- How do I automatically updated it here? -->
</div>
JS
// declare the app with no dependencies
var myApp = angular.module('myApp', []);
// make a factory to share data between controllers
myApp.factory('Data', function(){
// I know this doesn't work, but what will?
var FirstName = '';
return FirstName;
});
// Step 1 Controller
myApp.controller('FirstCtrl', function( $scope, Data ){
});
// Step 2 Controller
myApp.controller('SecondCtrl', function( $scope, Data ){
$scope.FirstName = Data.FirstName;
});
任何幫助是極大的贊賞。
一個簡單的解決方案是讓您的工廠返回一個對象,並讓您的控制器使用對同一對象的引用:
JS:
// declare the app with no dependencies
var myApp = angular.module('myApp', []);
// Create the factory that share the Fact
myApp.factory('Fact', function(){
return { Field: '' };
});
// Two controllers sharing an object that has a string in it
myApp.controller('FirstCtrl', function( $scope, Fact ){
$scope.Alpha = Fact;
});
myApp.controller('SecondCtrl', function( $scope, Fact ){
$scope.Beta = Fact;
});
HTML:
<div ng-controller="FirstCtrl">
<input type="text" ng-model="Alpha.Field">
First {{Alpha.Field}}
</div>
<div ng-controller="SecondCtrl">
<input type="text" ng-model="Beta.Field">
Second {{Beta.Field}}
</div>
演示: http : //jsfiddle.net/HEdJF/
當應用程序變得更大、更復雜且更難測試時,您可能不希望以這種方式從工廠公開整個對象,而是通過 getter 和 setter 等方式提供有限的訪問權限:
myApp.factory('Data', function () {
var data = {
FirstName: ''
};
return {
getFirstName: function () {
return data.FirstName;
},
setFirstName: function (firstName) {
data.FirstName = firstName;
}
};
});
使用這種方法,由消費控制器使用新值更新工廠,並觀察更改以獲取它們:
myApp.controller('FirstCtrl', function ($scope, Data) {
$scope.firstName = '';
$scope.$watch('firstName', function (newValue, oldValue) {
if (newValue !== oldValue) Data.setFirstName(newValue);
});
});
myApp.controller('SecondCtrl', function ($scope, Data) {
$scope.$watch(function () { return Data.getFirstName(); }, function (newValue, oldValue) {
if (newValue !== oldValue) $scope.firstName = newValue;
});
});
HTML:
<div ng-controller="FirstCtrl">
<input type="text" ng-model="firstName">
<br>Input is : <strong>{{firstName}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
Input should also be here: {{firstName}}
</div>
演示: http : //jsfiddle.net/27mk1n1o/
我不想為此使用$watch
。 您可以只分配數據,而不是將整個服務分配給控制器的范圍。
JS:
var myApp = angular.module('myApp', []);
myApp.factory('MyService', function(){
return {
data: {
firstName: '',
lastName: ''
}
// Other methods or objects can go here
};
});
myApp.controller('FirstCtrl', function($scope, MyService){
$scope.data = MyService.data;
});
myApp.controller('SecondCtrl', function($scope, MyService){
$scope.data = MyService.data;
});
HTML:
<div ng-controller="FirstCtrl">
<input type="text" ng-model="data.firstName">
<br>Input is : <strong>{{data.firstName}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
Input should also be here: {{data.firstName}}
</div>
或者,您可以使用直接方法更新服務數據。
JS:
// A new factory with an update method
myApp.factory('MyService', function(){
return {
data: {
firstName: '',
lastName: ''
},
update: function(first, last) {
// Improve this method as needed
this.data.firstName = first;
this.data.lastName = last;
}
};
});
// Your controller can use the service's update method
myApp.controller('SecondCtrl', function($scope, MyService){
$scope.data = MyService.data;
$scope.updateData = function(first, last) {
MyService.update(first, last);
}
});
您可以通過多種方式在控制器之間共享數據
我不打算解釋,因為它已經有人解釋過了
使用$state.go
$state.go('book.name', {Name: 'XYZ'}); // then get parameter out of URL $state.params.Name;
$stateparam
工作方式與$state.go
類似,您將其作為對象從發送方控制器傳遞並使用 stateparam 在接收方控制器中收集
使用$rootscope
(a) 從子控制器向父控制器發送數據
$scope.Save(Obj,function(data) { $scope.$emit('savedata',data); //pass the data as the second parameter }); $scope.$on('savedata',function(event,data) { //receive the data as second parameter });
(b) 從父控制器向子控制器發送數據
$scope.SaveDB(Obj,function(data){ $scope.$broadcast('savedata',data); }); $scope.SaveDB(Obj,function(data){`enter code here` $rootScope.$broadcast('saveCallback',data); });
我創建了一個工廠來控制路由路徑模式之間的共享范圍,因此您可以在用戶在同一路由父路徑中導航時維護共享數據。
.controller('CadastroController', ['$scope', 'RouteSharedScope',
function($scope, routeSharedScope) {
var customerScope = routeSharedScope.scopeFor('/Customer');
//var indexScope = routeSharedScope.scopeFor('/');
}
])
因此,如果用戶轉到另一個路由路徑,例如“/Support”,路徑“/Customer”的共享數據將自動銷毀。 但是,如果用戶轉到“子”路徑(例如“/Customer/1”或“/Customer/list”)而不是這個,則范圍不會被破壞。
您可以在此處查看示例: http : //plnkr.co/edit/OL8of9
有多種方式可以在控制器之間共享數據
我們知道$rootscope
不是數據傳輸或通信的首選方式,因為它是一個全局范圍,可用於整個應用程序
對於 Angular Js 控制器之間的數據共享,Angular 服務是最佳實踐,例如。 .factory
,. .service
供參考
如果數據從父控制器傳輸到子控制器,您可以通過$scope
直接訪問子控制器中的父數據
如果您使用的是ui-router
那么您可以使用$stateParmas
來傳遞id
、 name
、 key
等 url 參數
$broadcast
也是在控制器之間從父控制器傳輸數據到子控制器和$emit
將數據從子控制器傳輸到父控制器的好方法
HTML
<div ng-controller="FirstCtrl">
<input type="text" ng-model="FirstName">
<br>Input is : <strong>{{FirstName}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
Input should also be here: {{FirstName}}
</div>
JS
myApp.controller('FirstCtrl', function( $rootScope, Data ){
$rootScope.$broadcast('myData', {'FirstName': 'Peter'})
});
myApp.controller('SecondCtrl', function( $rootScope, Data ){
$rootScope.$on('myData', function(event, data) {
$scope.FirstName = data;
console.log(data); // Check in console how data is coming
});
});
請參閱給定鏈接以了解有關$broadcast
更多信息
我使用了AngularJS 服務。
第 1步:我創建了一個名為 SharedDataService 的 AngularJS 服務。
myApp.service('SharedDataService', function () {
var Person = {
name: ''
};
return Person;
});
Step2:創建兩個控制器,使用上面創建的服務。
//First Controller
myApp.controller("FirstCtrl", ['$scope', 'SharedDataService',
function ($scope, SharedDataService) {
$scope.Person = SharedDataService;
}]);
//Second Controller
myApp.controller("SecondCtrl", ['$scope', 'SharedDataService',
function ($scope, SharedDataService) {
$scope.Person = SharedDataService;
}]);
Step3:只需在視圖中使用創建的控制器。
<body ng-app="myApp">
<div ng-controller="FirstCtrl">
<input type="text" ng-model="Person.name">
<br>Input is : <strong>{{Person.name}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
Input should also be here: {{Person.name}}
</div>
</body>
要查看此問題的有效解決方案,請按以下鏈接
https://codepen.io/wins/pen/bmoYLr
.html 文件:
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="FirstCtrl">
<input type="text" ng-model="Person.name">
<br>Input is : <strong>{{Person.name}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
Input should also be here: {{Person.name}}
</div>
//Script starts from here
<script>
var myApp = angular.module("myApp",[]);
//create SharedDataService
myApp.service('SharedDataService', function () {
var Person = {
name: ''
};
return Person;
});
//First Controller
myApp.controller("FirstCtrl", ['$scope', 'SharedDataService',
function ($scope, SharedDataService) {
$scope.Person = SharedDataService;
}]);
//Second Controller
myApp.controller("SecondCtrl", ['$scope', 'SharedDataService',
function ($scope, SharedDataService) {
$scope.Person = SharedDataService;
}]);
</script>
</body>
</html>
還有另一種不使用 $watch 的方法,使用 angular.copy:
var myApp = angular.module('myApp', []);
myApp.factory('Data', function(){
var service = {
FirstName: '',
setFirstName: function(name) {
// this is the trick to sync the data
// so no need for a $watch function
// call this from anywhere when you need to update FirstName
angular.copy(name, service.FirstName);
}
};
return service;
});
// Step 1 Controller
myApp.controller('FirstCtrl', function( $scope, Data ){
});
// Step 2 Controller
myApp.controller('SecondCtrl', function( $scope, Data ){
$scope.FirstName = Data.FirstName;
});
有多種方法可以做到這一點。
事件 - 已經解釋得很好。
ui 路由器 - 上面解釋過。
*
<superhero flight speed strength> Superman is here! </superhero>
<superhero speed> Flash is here! </superhero>
*
app.directive('superhero', function(){
return {
restrict: 'E',
scope:{}, // IMPORTANT - to make the scope isolated else we will pollute it in case of a multiple components.
controller: function($scope){
$scope.abilities = [];
this.addStrength = function(){
$scope.abilities.push("strength");
}
this.addSpeed = function(){
$scope.abilities.push("speed");
}
this.addFlight = function(){
$scope.abilities.push("flight");
}
},
link: function(scope, element, attrs){
element.addClass('button');
element.on('mouseenter', function(){
console.log(scope.abilities);
})
}
}
});
app.directive('strength', function(){
return{
require:'superhero',
link: function(scope, element, attrs, superHeroCtrl){
superHeroCtrl.addStrength();
}
}
});
app.directive('speed', function(){
return{
require:'superhero',
link: function(scope, element, attrs, superHeroCtrl){
superHeroCtrl.addSpeed();
}
}
});
app.directive('flight', function(){
return{
require:'superhero',
link: function(scope, element, attrs, superHeroCtrl){
superHeroCtrl.addFlight();
}
}
});
不知道我從哪里學到了這種模式,但為了在控制器之間共享數據並減少 $rootScope 和 $scope 這很有效。 它讓人想起有發布者和訂閱者的數據復制。 希望能幫助到你。
服務:
(function(app) {
"use strict";
app.factory("sharedDataEventHub", sharedDataEventHub);
sharedDataEventHub.$inject = ["$rootScope"];
function sharedDataEventHub($rootScope) {
var DATA_CHANGE = "DATA_CHANGE_EVENT";
var service = {
changeData: changeData,
onChangeData: onChangeData
};
return service;
function changeData(obj) {
$rootScope.$broadcast(DATA_CHANGE, obj);
}
function onChangeData($scope, handler) {
$scope.$on(DATA_CHANGE, function(event, obj) {
handler(obj);
});
}
}
}(app));
獲取新數據的控制器,即發布者會做這樣的事情..
var someData = yourDataService.getSomeData();
sharedDataEventHub.changeData(someData);
也使用這個新數據的控制器,稱為訂閱者會做這樣的事情......
sharedDataEventHub.onChangeData($scope, function(data) {
vm.localData.Property1 = data.Property1;
vm.localData.Property2 = data.Property2;
});
這適用於任何場景。 因此,當主控制器初始化並獲取數據時,它會調用 changeData 方法,然后將其廣播給該數據的所有訂閱者。 這減少了我們的控制器之間的耦合。
正如@MaNn 在已接受答案的評論之一中指出的那樣,如果刷新頁面,該解決方案將不起作用。
解決方案是使用 localStorage 或 sessionStorage 來臨時持久化要跨控制器共享的數據。
做簡單的事情(用 v1.3.15 測試):
<article ng-controller="ctrl1 as c1">
<label>Change name here:</label>
<input ng-model="c1.sData.name" />
<h1>Control 1: {{c1.sData.name}}, {{c1.sData.age}}</h1>
</article>
<article ng-controller="ctrl2 as c2">
<label>Change age here:</label>
<input ng-model="c2.sData.age" />
<h1>Control 2: {{c2.sData.name}}, {{c2.sData.age}}</h1>
</article>
<script>
var app = angular.module("MyApp", []);
var dummy = {name: "Joe", age: 25};
app.controller("ctrl1", function () {
this.sData = dummy;
});
app.controller("ctrl2", function () {
this.sData = dummy;
});
</script>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.