Reputation: 2368
When working on a project, as these things tend to happen, we came across a situation where we were stumped on how to update certain UI elements when other things were done. For example, the navigation contains a counter of how many pending activities are due today. At any point in time during usage of the app, a user might schedule an activity for later today, and the count section would need to call the API to generate a count and the drop-down items associated with it.
How can I make a navigation controller pull the new list of activities when the main controller makes a change?
See this code for an example.
<div ng-app="TestApp">
<nav ng-controller="navigationController">
<p>The navigation count is: {{items.length}}</p>
</nav>
<div ng-controller="mainController">
<p>The main count is: {{items.length}}</p>
<p>
<button ng-click="addItem()" type="button">Add item.</button>
</p>
</div>
</div>
<script>
var app = angular.module('TestApp', []);
app.factory("api", function() {
return {
update: function() {
return ['a', 'b', 'c', 'd', 'e'];
}
};
});
app.factory("sharedFactory", function(api) {
var obj = {};
obj.items = ["a"];
obj.update = function() {
obj.items = api.update();
};
return obj;
});
app.controller("mainController", function(sharedFactory, $scope) {
$scope.items = sharedFactory.items;
$scope.addItem = function() {
sharedFactory.update();
};
});
app.controller("navigationController", function(sharedFactory, $scope) {
$scope.items = sharedFactory.items;
});
</script>
Our current solution was to create a callback service that other controllers could subscribe to, and then when an activity was created have those callbacks run as needed. This works nicely, but I'm nervous that I'm "doing it wrong".
We're switching to the Angular UI Router, now, so I'm curious if there's a better way of doing so in it. Right now our navigation handler is a stateless controller that hooks into our callback service still.
Upvotes: 2
Views: 553
Reputation: 2075
However you feel about MVC, you could use angular's internals to automatically do this:
https://jsfiddle.net/gkmtkxpm/
var myApp = angular.module('myApp', []);
myApp.factory('counter', function() {
return {
count: 0
};
});
myApp.controller('CounterController', function (counter) {
var vm = this;
vm.counter = counter;
vm.increment = function() {
vm.counter.count = vm.counter.count + 1;
};
});
edit: Concerning your updated question, see the updated fiddle: https://jsfiddle.net/gkmtkxpm/1/
Upvotes: 1
Reputation: 36
A nice way to handle this could be to use $scope.$on
to listen for events, and $scope.$emit
to fire an event going up the scope or $scope.$broadcast
to fire an even going down the scope.
In each piece of the UI that needs to be updated can be listening with $scope.$on
and update itself when an event is fired, like your user scheduling an event for later today.
Angular docs for $on, $emit and $broadcast
Upvotes: 1
Reputation: 330
Though I generally think that registering scope values on a controller with a service is the best way to accomplish another option would be to use a factory and set a property of that on scope.
angular.module('app').factory('myService', function() {
var myService = {};
service.count = 0;
/// other service functions
return myService;
}
angular.module('app').controller('myController', function(myService) {
this.count = myService.count;
}
Upvotes: 1