我有一个页面,其中一个控制器显示所有登录用户的团队,另一个控制器允许用户更新团队。当用户更新团队名称时,我希望显示所有团队的控制器注意到团队已更新并相应地更新其变量。
我一直在谷歌搜索,似乎有很多问题和许多不同的方法来做到这一点。理想情况下,我希望能够只更新工厂变量,并且所有控制器都会注意到该值已更新。不确定这是否有角度的作用。
示例:
var myapp= angular.module('myapp', []);
...
// This gets the teams that a user is associated with
myezteam.factory('teams', function($http) {
// Get the teams associated with the logged in user
return {
getTeams: function(callback) {
$http.get(baseUrl+'v1/teams/all' + apiKey)
.success(function(response) {
callback(response);
});
}
}
});
获得所有团队的控制器
// This controller is used to set the user profile links
myapp.controller('TemplateProfileController', ['$scope', '$http'', 'teams', function($scope, $http, teams) {
// Gets all of a user's teams from the "teams" factory
getTeams = function() {
teams.getTeams(function(response) {
$scope.teams = response;
});
}
$scope.teams = getTeams(); // Call on page load
}]);
处理团队编辑的控制器
// Controller for editing a team
myapp.controller('EditTeamController', ['$scope', '$http', '$routeParams', 'teams', function($scope, $http, $routeParams, teams) {
// Get the team that we're editing
getTeam = function() {
$http.get(baseUrl+'v1/teams/' + $routeParams.id + apiKey)
.success(function(response) {
$scope.team = response;
});
}
// Update the team and refresh the list of all teams
$scope.updateTeam = function() {
$http.post(baseUrl+'v1/teams' + apiKey, $scope.team)
.success(function(response) {
// NEED TO SOMEONE TRIGGER THE TempalteProfileController to get the teams from the factory again
})
}
getTeam(); // Call on page load;
}]);
答案 0 :(得分:10)
只要您了解变量和对象之间的区别,这实际上非常简单。
假设我有一个跟踪计数器的服务并提供增加它的方法:
app.factory("mySharedService", function(){
var values = {
mySharedValue: 0
};
return{
getValues: function(){
return values;
},
incrementValue: function(){
values.mySharedValue++;
}
};
});
请注意,我声明一个对象并挂起对象的实际值,而不是仅仅声明一个简单的变量。此对象引用在服务的生命周期内将保持不变,并且只有其中的值将更改。
这意味着任何调用getValues()
的控制器都将收到相同的对象引用,并且可以在其范围内使用它:
app.controller('Controller1', function($scope, mySharedService) {
$scope.values = mySharedService.getValues();
});
app.controller('Controller2', function($scope, mySharedService) {
$scope.values = mySharedService.getValues();
});
app.controller('Controller3', function($scope, mySharedService) {
$scope.values = mySharedService.getValues();
});
每当mySharedValue
中的值发生变化时,所有控制器都会看到它(因为它们都共享相同的对象引用)。这意味着该控制器中的任何绑定都会立即更新,您可以像使用任何其他范围变量一样使用$scope.$watch()
。
以下是一个示例摘要:
http://plnkr.co/edit/FA3MbfQQpiOtp5mGqqAq?p=preview
编辑:
如果您想保留封装并且只能通过提供的方法编辑值,您可以执行以下操作:
app.factory("mySharedService", function(){
var mySharedValue = 0;
var values = {
getMySharedValue: function(){
return mySharedValue;
}
};
return{
getValues: function(){
return values;
},
incrementValue: function(){
mySharedValue++;
}
};
});
答案 1 :(得分:2)
最简单的方法是将团队放在$ rootScope上,这样所有将使用团队的控制器都可以使用它。我发现这是CRUD应用程序的最佳解决方案,你有一个“列表”控制器和一个“新”控制器,“编辑”等......
我花了一些时间来熟悉它,因为我看到使用$ rootScope就像使用全局变量一样;然而,我听到Misko(angularjs的创建者)在演讲中回答了某人的问题,他说“为什么不把它放在rootScope上”。他似乎并不像我那样担心。
最重要的是 - 当你在$ rootScope上添加一些内容时,它会使代码变得更清晰 - 我开始广播和监听事件,代码更加混乱。
最终,我看到它的方式,如果您的页面/应用程序的唯一目的是展示团队 - 并且您有多个控制器处理它 - 将它放在$ rootScope上是有意义的。
长话短说,用$scope.teams
替换$rootScope.teams
,并确保在控制器构造函数中包含$ rootScope以进行依赖注入。
答案 2 :(得分:1)
@Catfish
您可以在服务变量中添加$ watch,就像他的答案中提到的@dtabuenc一样。这就是它的样子:
app.controller('Controller1', function($scope, mySharedService) {
$scope.values = mySharedService.getValues();
$scope.$watch( function () { return mySharedService.getValues(); }, function () {
alert('data changed');
}, true);
});
答案 3 :(得分:0)
您可以使用服务来实现这一目标。 看到它在这里工作 http://plnkr.co/edit/TAIJlm?p=preview
HTML:
<body ng-app='myapp'>
<div id="col1" ng-controller="MainCtrl">
<h1>MainCtrl teams:</h1>
<ul>
<li ng-repeat='t in teams'>{{t}}</li>
</ul>
<button ng-click="updateTeam()">Add team</button>
</div>
<div id="col2" ng-controller="OtherCtrl">
<h1>OtherCtrl teams:</h1>
<ul>
<li ng-repeat='t in otherTeams'>{{t}}</li>
</ul>
</div>
</body>
JS:
angular.module('myapp', [])
.service('Teams', function($http, $q) {
var _teams = [];
var defer = $q.defer();
$http.get('teams.json')
.success(function(response) {
_teams = JSON.parse(response[0]);
defer.resolve(_teams);
})
.error(function(err) {
defer.reject(err);
});
// _teams = [1,2,3,4,5];
// Get the teams associated with the logged in user
return {
getTeams: function getTeams() {
return defer.promise;
}
}
})
.controller('MainCtrl', function($scope, Teams) {
Teams.getTeams().then(function(teams) {
$scope.teams = teams;
});
// Update the team and refresh the list of all teams
$scope.updateTeam = function() {
$scope.teams.push($scope.teams.length+1);
};
})
.controller('OtherCtrl', function($scope, Teams) {
Teams.getTeams().then(function(teams) {
$scope.otherTeams = teams;
});
});
双向数据绑定通过在作用域引用的数组发生更改时更新视图来实现其魔力。
答案 4 :(得分:0)
@dtabuenc和@xdotcommer提出了一些有效的解决方案。但如果您想在数据更新时在控制器中执行某些操作,则可以使用$ rootScope。$ emit + $ rootScope。$ on。
在你的工厂:
$rootScope.$emit('dataChangedEvent', data);
在您的控制器中:
$rootScope.$on('dataChangedEvent', function(event, data) {console.log(data)});