I've been trying to code up a search engine using angular js, but I can't copy one array to another. When I initiate the the code (in the service.FoundItems in the q.all then function) new array(foundArray) shows up as an empty array. I searched up how to copy one array to another and tried that method as you can see, but it isn't working. Please help, here is the code, and thank you.
P.S. if you need the html please tell me.
(function () {
'use strict';
angular.module('narrowDownMenuApp', [])
.controller('narrowItDownController', narrowItDownController)
.service('MenuSearchService', MenuSearchService)
.directive('searchResult', searchResultDirective);
function searchResultDirective() {
var ddo = {
templateUrl: 'searchResult.html',
scope: {
items: '<'
},
};
return ddo
}
narrowItDownController.$inject = ['MenuSearchService'];
function narrowItDownController(MenuSearchService) {
var menu = this;
menu.input = "";
menu.displayResult = [];
menu.searchX = function(name) {
menu.displayResult = MenuSearchService.FoundItems(menu.input, name);
console.log(menu.displayResult);
};
}
MenuSearchService.$inject = ['$http', '$q'];
function MenuSearchService($http, $q) {
var service = this;
service.getMatchedMenuItems = function(name, searchTerm) {
var deferred = $q.defer();
var foundItems = [];
var result = $http({
method: "GET",
url: ('https://davids-restaurant.herokuapp.com/menu_items.json'),
params: {
category: name
}
}).then(function (result) {
var items = result.data;
for (var i = 0; i < items.menu_items.length; i++) {
if (searchTerm === ""){
deferred.reject("Please enter search term");
i = items.menu_items.length;
}
else if (items.menu_items[i].name.toLowerCase().indexOf(searchTerm.toLowerCase()) ==! -1){
foundItems.push(items.menu_items[i].name)
deferred.resolve(foundItems);
}else {
console.log("doesn't match search");
}
}
});
return deferred.promise;
};
service.FoundItems = function (searchTerm, name) {
var searchResult = service.getMatchedMenuItems(name, searchTerm);
var foundArray = [];
$q.all([searchResult])
.then(function (foundItems) {
foundArray = foundItems[0].slice(0);
foundArray.reverse();
})
.catch(function (errorResponse) {
foundArray.push(errorResponse);
});
console.log(foundArray);
return foundArray;
};
};
})();
If the goal of the service.FoundItems function is to return a reference to an array that is later populated with results from the server, use angular.copy to copy the new array from the server to the existing array:
service.FoundItems = function (searchTerm, name) {
var foundArray = [];
var searchPromise = service.getMatchedMenuItems(name, searchTerm);
foundArray.$promise = searchPromise
.then(function (foundItems) {
angular.copy(foundItems, foundArray);
foundArray.reverse();
return foundArray;
})
.catch(function (errorResponse) {
return $q.reject(errorResponse);
})
.finally(function() {
console.log(foundArray);
});
return foundArray;
};
I recommend that the promise be attached to the array reference as a property named $promise so that it can be used to chain functions that depend on results from the server.
Frankly I don't recommend designing services that return array references that are later populated with results. If you insist on designing it that way, this is how it is done.
I tried the $promise thing that you recommended. I was wondering how you would get the value from it ie the array.
In the controller, use the .then method of the $promise to see the final value of the array:
narrowItDownController.$inject = ['MenuSearchService'];
function narrowItDownController(MenuSearchService) {
var menu = this;
menu.input = "";
menu.displayResult = [];
menu.searchX = function(name) {
menu.displayResult = MenuSearchService.FoundItems(menu.input, name);
̶c̶o̶n̶s̶o̶l̶e̶.̶l̶o̶g̶(̶m̶e̶n̶u̶.̶d̶i̶s̶p̶l̶a̶y̶R̶e̶s̶u̶l̶t̶)̶;̶
menu.displayResult.$promise
.then(function(foundArray) {
console.log(foundArray);
console.log(menu.displayResult);
}).catch(function(errorResponse) {
console.log("ERROR");
console.log(errorResponse);
});
};
}
To see the final result, the console.log needs to be moved inside the .then block of the promise.
Titus is right. The function always immediately returns the initial value of foundArray which is an empty array. The promise is executed asynchronously so by the time you are trying to change foundArray it is too late. You need to return the promise itself and then using .then() to retrieve the value just like you are currently doing inside the method.
From just quickly looking at your code I think you made have a simple error in there. Are you sure you want
foundArray = foundItems[0].slice(0);
instead of
foundArray = foundItems.slice(0);
Related
Factory that gets the rates using REST
.factory('rateResource', ['$resource', function ($resource) {
return $resource('/rates/:currency/:effectiveDate', {
currency: '#currency',
effectiveDate: '#effectiveDate'
});
}])
Service that calls the factory to get resource and retrieve the rates and also errors if there are any.
.service('RateService', ['rateResource', '$rootScope',
function (rateResource, $rootScope) {
var self = this;
self.rates = [];
self.search = function (baseCurrency, effectiveDate) {
self.rates = [];
var error = null;
self.baseCurrency = baseCurrency;
self.effectiveDate = effectiveDate;
if (baseCurrency) {
rateResource.query({currency: baseCurrency, effectiveDate: effectiveDate})
.$promise.then(function (rates) {
if (rates) {
angular.forEach(rates, function (rate) {
rate.maintTs = $rootScope.formatTimestampToHHMMSS(rate.maintTs);
rate.editable = false;
self.rates.push(rate);
});
self.processing = false;
}
}, function (response) {
self.processing = false;
error = 'Processing failed due to '+response.status;
console.log(error);
})
return {
rates: self.rates,
errors: error
}
}
}
}]);
Controller calls the service for rates.
.controller('RateController', ['RateService',
function (rateService) {
var self = this;
self.baseCurrency = rateService.getBaseCurrency();
self.effectiveDate = rateService.getEffectiveDate();
self.rates = rateService.getRates();
//make the call from the controller
self.search = function () {
var response = rateService.search(self.baseCurrency, self.effectiveDate.yyyyMMdd());
self.rateRecords = response.rates;
self.errors = response.errors;
}
}])
rates are showing up fine in the controller after the promise is fulfilled. However, upon receiving errors, they are not getting transferred from service to controller. ( I changed the REST URL to make service return a 404 response ). What am I doing wrong?
Currently you are returning asynchronous call response from outside of async function, you shouldn't do that technically. Asynchronous code always get there responses inside their promise/callback function.
But in your case it is working because you are returning object with it reference. If you look at below code, return statement has carried self.rates object reference, so while returning even if it is blank, it is going to get updated value once self.rates gets filled up. So then you don't need to worry about the rates updation. But same thing for error would not work because it is of primitive datatype like var error = null, so when you are returning value it would be null(as async response haven't completed).
return {
rates: self.rates, //passed by reference
errors: error //passed by primitive type
}
So for solving this issue you could also make the error to an object type, so that it reference will get passed with reference object, like var errors = [] & when error occur push the error message into that array using .push
But I'd not recommend above way to go for, I'd rather take use of promise pattern and will maintain proper code call stack. Basically for that you need to return promise from search method & then put .then function to wait till resolve that function.
Service
.service('RateService', ['rateResource', '$rootScope',
function(rateResource, $rootScope) {
var self = this;
self.rates = [];
self.search = function(baseCurrency, effectiveDate) {
self.rates = [];
var error = null;
self.baseCurrency = baseCurrency;
self.effectiveDate = effectiveDate;
if (baseCurrency) {
return rateResource.query({
currency: baseCurrency,
effectiveDate: effectiveDate
})
.$promise.then(function(rates) {
if (rates) {
angular.forEach(rates, function(rate) {
rate.maintTs = $rootScope.formatTimestampToHHMMSS(rate.maintTs);
rate.editable = false;
self.rates.push(rate);
});
self.processing = false;
}
//returning object from promise
return {
rates: self.rates,
errors: error
}
}, function(response) {
self.processing = false;
error = 'Processing failed due to ' + response.status;
console.log(error);
//returning object from promise
return {
rates: self.rates,
errors: error
}
})
}
}
}
])
Controller
//make the call from the controller
self.search = function() {
var response = rateService.search(self.baseCurrency, self.effectiveDate.yyyyMMdd()).then(function() {
self.rateRecords = response.rates;
self.errors = response.errors;
});
}
Here is my controller
angular.module("app").controller('myController', ['$scope', '$filter','$rootScope','contentService','$location','$anchorScroll', function ($scope, $filter,$rootScope,contentService,$location,$anchorScroll) {
$scope.searchContents = [] ;
var filterList = function (list, keyword) {
return $filter('filter')(list, keyword);
};
var addToSearchContents = function (list,type){
_.each(list,function(item){
item.type = type;
$scope.searchContents.push(item);
});
};
$scope.init = function(){
var str = $location.absUrl();
$scope.searchKeyword = str.substring(str.indexOf("=") + 1,str.length);
!_.isEmpty($scope.searchKeyword)
{
// get all songs
contentService.getAllSongs().then(function (result) {
var filteredSongs = filterList(result.data.songs, $scope.searchKeyword);
addToSearchContents(filteredSongs,"song");
});
// get all people
contentService.getAllPeople().then(function (result) {
var filteredPeople = filterList(result.data.people, $scope.searchKeyword);
addToSearchContents(filteredPeople,"people");
});
_.each($scope.searchContents,function(item){
alert("item -> "+item.type);
});
}
};
$scope.init();
}]);
Items(objects) are added to the variable $scope.searchContents in addToSearchContents but if i try to access/iterate after all objects that are pushed to $scope.searchContents with _.each it seems to null. But i can access all the contents in HTML page with ng-repeat but not in controller. I am puzzled, am i missing something.
You got the error because when you call _.each($scope.searchContents..., the data has not arrived from the async calls. addToSearchContents is not executed yet.
Use $q.all, which combines all promises into on giant one. And then do something after all promises are resolved.
Note: remember to inject the service $q to your controller.
$q.all([
contentService.getAllSongs(),
contentService.getAllPeople()
]).then(function (result) {
// `result` is an array containing the results from the promises.
var filteredSongs = filterList(result[0].data.songs, $scope.searchKeyword);
addToSearchContents(filteredSongs,"song");
var filteredPeople = filterList(result[1].data.people, $scope.searchKeyword);
addToSearchContents(filteredPeople,"people");
_.each($scope.searchContents,function(item){
alert("item -> "+item.type);
});
});
I do not have your coding context, so a similar JSFiddle is created for you. It illustrates the same idea.
Yet another variant, also with $q.all:
$q.all([
// get all songs
contentService.getAllSongs().then(function (result) {
var filteredSongs = filterList(result.data.songs, $scope.searchKeyword);
addToSearchContents(filteredSongs,"song");
}),
// get all people
contentService.getAllPeople().then(function (result) {
var filteredPeople = filterList(result.data.people, $scope.searchKeyword);
addToSearchContents(filteredPeople,"people");
})]).then(function(){
// here all items already added so we can iterate it
_.each($scope.searchContents,function(item){
alert("item -> "+item.type);
});
});
I'm trying to access a return promise data, but it always give me undefined even when i'm accessing to the correct element.
here is why i have to do it that way .
controller.js
// can't access the data "tastes" in success outside from the .success call
// so i return the entire http call and access it later
function loadContacts() {
var contacts;
return Account.getTastes()
.success(function(tastes) {
contacts= tastes[0].tastes;
return contacts.map(function (c, index) {
var colors = ["1abc9c", "16a085", "f1c40f", "f39c12", "2ecc71", "27ae60", "e67e22","d35400","3498db","2980b9","e74c3c","c0392b","9b59b6","8e44ad","34495e","2c3e50"];
var color = colors[Math.floor(Math.random() * colors.length)];
var cParts = c.split(' ');
var contact = {
name: c,
image: "http://dummyimage.com/50x50/"+color+"/f7f7f7.png&text="+c.charAt(0)
};
contact._lowername = contact.name.toLowerCase();
return contact;
});
})
.error(function(error) {
console.log("Error:"+error)
});
}
/**
* Search for contacts.
*/
function querySearch (query) {
var results = query ?
$scope.allContacts.filter(createFilterFor(query)) : [];
return results;
}
/**
* Create filter function for a query string
*/
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(contact) {
return (contact._lowername.indexOf(lowercaseQuery) != -1);;
};
}
$scope.allContacts = loadContacts();
console.log($scope.allContacts)
$scope.tags = [$scope.allContacts[0],$scope.allContacts[1]];
// since $scope.allContacts is undefined thus,
//i'm having error for trying to access element[0] of undefined
the console.log($scope.allContacts) result is
but when i try to access it like $scope.allContacts.$$state.value.data i get undefined as return. may i know what is the solution for this ?
in my html
<md-contact-chips required ng-model="tags" md-contacts="querySearch($query)" md-contact-name="name" md-contact-image="image" filter-selected="true" placeholder="Thai, chinese, cheap, cafe and etc">
</md-contact-chips>
UPDATE: 1(SOLVED)
i'm getting this error after i change my code to
$scope.allContacts.then(function(contacts){
$scope.tags = [contacts[0],contacts[1]];
})
Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: $chip in $mdChipsCtrl.items, Duplicate key: undefined:undefined, Duplicate value: undefined
i'm not even using ng-repeat why am i still getting ng-repeat error ?
UPDATE: 2
the chips is now being displayed however i can't search, when i try to search on the md-contact-chips this happened
You should be able to access contacts like so...
$scope.allContacts.then(function(contacts){
console.log(contacts[0]);
console.log(contacts[1]);
})
if you change
Account.getTastes().success
to
Account.getTastes().then
final results
function loadContacts() {
var contacts;
return Account.getTastes()
.then(function(res) {
contacts = res.data[0].tastes;
return contacts.map(function (c, index) {
var colors = ["1abc9c", "16a085", "f1c40f", "f39c12", "2ecc71", "27ae60", "e67e22","d35400","3498db","2980b9","e74c3c","c0392b","9b59b6","8e44ad","34495e","2c3e50"];
var color = colors[Math.floor(Math.random() * colors.length)];
var cParts = c.split(' ');
var contact = {
name: c,
image: "http://dummyimage.com/50x50/"+color+"/f7f7f7.png&text="+c.charAt(0)
};
contact._lowername = contact.name.toLowerCase();
return contact;
});
})
.error(function(error) {
console.log("Error:"+error)
});
}
$scope.allContacts = loadContacts();
console.log($scope.allContacts)
$scope.allContacts.then(function(contacts){
console.log(contacts[0]);
console.log(contacts[1]);
})
The main problem here seems to be that when you try to access the value, the promise is not resolved yet, so I guess it should be enough to wrap
$scope.tags = [$scope.allContacts[0],$scope.allContacts[1]];
into something like
$scope.allContacts.then(function(){
$scope.tags = [$scope.allContacts[0],$scope.allContacts[1]];
}
What I have is simple CRUD operation. Items are listed on page, when user clicks button add, modal pops up, user enters data, and data is saved and should automatically (without refresh)be added to the list on page.
Service:
getAllIncluding: function(controllerAction, including) {
var query = breeze.EntityQuery.from(controllerAction).expand(including);
return manager.executeQuery(query).fail(getFailed);
},
addExerciseAndCategories: function(data, initialValues) {
var addedExercise = manager.createEntity("Exercise", initialValues);
_.forEach(data, function(item) {
manager.createEntity("ExerciseAndCategory", { ExerciseId: addedExercise._backingStore.ExerciseId, CategoryId: item.CategoryId });
});
saveChanges().fail(addFailed);
function addFailed() {
removeItem(items, item);
}
},
Controller:
$scope.getAllExercisesAndCategories = function() {
adminCrudService.getAllIncluding("ExercisesAndCategories", "Exercise,ExerciseCategory")
.then(querySucceeded)
.fail(queryFailed);
};
function querySucceeded(data) {
$scope.queryItems = adminCrudService.querySucceeded(data);
var exerciseIds = _($scope.queryItems).pluck('ExerciseId').uniq().valueOf();
$scope.exerciseAndCategories = [];
var createItem = function (id, exercise) {
return {
ExerciseId: id,
Exercise : exercise,
ExerciseCategories: []
};
};
// cycle through ids
_.forEach(exerciseIds, function (id) {
// get all the queryItems that match
var temp = _.where($scope.queryItems, {
'ExerciseId': id
});
// go to the next if nothing was found.
if (!temp.length) return;
// create a new (clean) item
var newItem = createItem(temp[0].ExerciseId, temp[0].Exercise);
// loop through the queryItems that matched
_.forEach(temp, function (i) {
// if the category has not been added , add it.
if (_.indexOf(newItem.ExerciseCategories, i.ExerciseCategory) < 0) {
newItem.ExerciseCategories.push(i.ExerciseCategory);
}
});
// Add the item to the collection
$scope.items.push(newItem);
});
$scope.$apply();
}
Here is how I add new data from controller:
adminCrudService.addExerciseAndCategories($scope.selectedCategories, { Name: $scope.NewName, Description: $scope.NewDesc });
So my question is, why list isn't updated in real time (when I hit save I must refresh page).
EDIT
Here is my querySuceeded
querySucceeded: function (data) {
items = [];
data.results.forEach(function(item) {
items.push(item);
});
return items;
}
EDIT 2
I believe I've narrowed my problem !
So PW Kad lost two hours with me trying to help me to fix this thing (ad I thank him very very very much for that), but unfortunately with no success. We mostly tried to fix my service, so when I returned to my PC, I've again tried to fix it. I believe my service is fine. (I've made some changes as Kad suggested in his answer).
I believe problem is in controller, I've logged $scope.items, and when I add new item they don't change, after that I've logged $scope.queryItems, and I've noticed that they change after adding new item (without refresh ofc.). So probably problem will be solved by somehow $watching $scope.queryItems after loading initial data, but at the moment I'm not quite sure how to do this.
Alright, I am going to post an answer that should guide you on how to tackle your issue. The issue does not appear to be with Breeze, nor with Angular, but the manner in which you have married the two up. I say this because it is important to understand what you are doing in order to understand the debug process.
Creating an entity adds it to the cache with an entityState of isAdded - that is a true statement, don't think otherwise.
Now for your code...
You don't have to chain your query execution with a promise, but in your case you are returning the data to your controller, and then passing it right back into some function in your service, which wasn't listed in your question. I added a function to replicate what yours probably looks like.
getAllIncluding: function(controllerAction, including) {
var query = breeze.EntityQuery.from(controllerAction).expand(including);
return manager.executeQuery(query).then(querySucceeded).fail(getFailed);
function querySucceeded(data) {
return data.results;
}
},
Now in your controller simply handle the results -
$scope.getAllExercisesAndCategories = function() {
adminCrudService.getAllIncluding("ExercisesAndCategories", "Exercise,ExerciseCategory")
.then(querySucceeded)
.fail(queryFailed);
};
function querySucceeded(data) {
// Set your object directly to the data.results, because that is what we are returning from the service
$scope.queryItems = data;
$scope.exerciseAndCategories = [];
Last, let's add the properties we create the entity and see if that gives Angular a chance to bind up properly -
_.forEach(data, function(item) {
var e = manager.createEntity("ExerciseAndCategory");
e.Exercise = addedExercise; e.Category: item.Category;
});
So I've managed to solve my problem ! Not sure if this is right solution but it works now.
I've moved everything to my service, which now looks like this:
function addCategoriesToExercise(tempdata) {
var dataToReturn = [];
var exerciseIds = _(tempdata).pluck('ExerciseId').uniq().valueOf();
var createItem = function (id, exercise) {
return {
ExerciseId: id,
Exercise: exercise,
ExerciseCategories: []
};
};
// cycle through ids
_.forEach(exerciseIds, function (id) {
// get all the queryItems that match
var temp = _.where(tempdata, {
'ExerciseId': id
});
// go to the next if nothing was found.
if (!temp.length) return;
// create a new (clean) item
var newItem = createItem(temp[0].ExerciseId, temp[0].Exercise);
// loop through the queryItems that matched
_.forEach(temp, function (i) {
// if the category has not been added , add it.
if (_.indexOf(newItem.ExerciseCategories, i.ExerciseCategory) < 0) {
newItem.ExerciseCategories.push(i.ExerciseCategory);
}
});
// Add the item to the collection
dataToReturn.push(newItem);
});
return dataToReturn;
}
addExerciseAndCategories: function (data, initialValues) {
newItems = [];
var addedExercise = manager.createEntity("Exercise", initialValues);
_.forEach(data, function (item) {
var entity = manager.createEntity("ExerciseAndCategory", { ExerciseId: addedExercise._backingStore.ExerciseId, CategoryId: item.CategoryId });
items.push(entity);
newItems.push(entity);
});
saveChanges().fail(addFailed);
var itemsToAdd = addCategoriesToExercise(newItems);
_.forEach(itemsToAdd, function (item) {
exerciseAndCategories.push(item);
});
function addFailed() {
removeItem(items, item);
}
}
getAllExercisesAndCategories: function () {
var query = breeze.EntityQuery.from("ExercisesAndCategories").expand("Exercise,ExerciseCategory");
return manager.executeQuery(query).then(getSuceeded).fail(getFailed);
},
function getSuceeded(data) {
items = [];
data.results.forEach(function (item) {
items.push(item);
});
exerciseAndCategories = addCategoriesToExercise(items);
return exerciseAndCategories;
}
And in controller I have only this:
$scope.getAllExercisesAndCategories = function () {
adminExerciseService.getAllExercisesAndCategories()
.then(querySucceeded)
.fail(queryFailed);
};
function querySucceeded(data) {
$scope.items = data;
$scope.$apply();
}
I have quite a few scenarios where I need clicks, etc. to trigger behavior in another place on the page (a one-way communication scenario). I now have a need for bi-directional communication, where stuff that happens in element A can modify specific properties in the scope behind element B and vice-versa. Thus far, I've been using $rootScope.$broadcast to facilitate this but it feels like overkill, and winds up creating boilerplate in both places:
$scope.$on('event-name', function(event, someArg) {
if(someArg === $scope.someProperty) return;
$scope.someProperty = someArg;
});
$scope.$watch('someProperty', function(newValue) {
$rootScope.$broadcast('event-name', newValue);
});
Is there a better way? I'd like to tie the two (or three, or N) scopes together via a service, but I don't see a way to do that without magic event names and boilerplate.
I haven't used this myself, but this post explains basically how I would do it. Here's the code which illustrates the idea:
(function() {
var mod = angular.module("App.services", []);
//register other services here...
/* pubsub - based on https://github.com/phiggins42/bloody-jquery-plugins/blob/master/pubsub.js*/
mod.factory('pubsub', function() {
var cache = {};
return {
publish: function(topic, args) {
cache[topic] && $.each(cache[topic], function() {
this.apply(null, args || []);
});
},
subscribe: function(topic, callback) {
if(!cache[topic]) {
cache[topic] = [];
}
cache[topic].push(callback);
return [topic, callback];
},
unsubscribe: function(handle) {
var t = handle[0];
cache[t] && d.each(cache[t], function(idx){
if(this == handle[1]){
cache[t].splice(idx, 1);
}
});
}
}
});
return mod;
})();
Note the memory leak though if controllers are "deleted" without unsubscribing.
I think you can try the following service,
'use strict';
angular.module('test')
.service('messageBus', function($q) {
var subscriptions = {};
var pendingQuestions = [];
this.subscribe = function(name) {
subscriptions[name].requestDefer = $q.defer();
return subscriptions[name].requestDefer.promise; //for outgoing notifications
}
this.unsubscribe = function(name) {
subscriptions[name].requestDefer.resolve();
subscriptions[name].requestDefer = null;
}
function publish(name, data) {
subscriptions[name].requestDefer.notify(data);
}
//name = whom shd answer ?
//code = what is the question ?
//details = details abt question.
this.request = function(name, code, details) {
var defered = null;
if (subscriptions[name].requestDefer) {
if (pendingQuestions[code]) {
//means this question is already been waiting for answer.
//hence return the same promise. A promise with multiple handler will get
//same data.
defered = pendingQuestions[code];
} else {
defered = $q.defer();
//this will be resolved by response method.
pendingQuestions[code] = defered;
//asking question to relevant controller
publish(name, {
code: code,
details: details
});
}
} else {
//means that one is not currently in hand shaked with service.
defered = $q.defer();
defered.resolve({
code: "not subscribed"
});
}
return defered.promise;
}
//data = code + details
//responder does not know the destination. This will be handled by the service using
//pendingQuestions[] array. or it is preemptive, so decide by code.
this.response = function(data) {
var defered = pendingQuestions[data.code];
if (defered) {
defered.resolve(data);
} else {
//means nobody requested for this.
handlePreemptiveNotifications(data);
}
}
function handlePreemptiveNotifications() {
switch (data.code) {
//handle them case by case
}
}
});
This can be used as a message bus in multi controller communication. It is making use of the angular notify() callback of promise API.All the participating controllers should subscribe the service as follows,
angular.module('test')
.controller('Controller1', function($scope, messageBus) {
var name = "controller1";
function load() {
var subscriber = messageBus.subscribe(name);
subscriber.then(null, null, function(data) {
handleRequestFromService(data);
});
}
function handleRequestFromService(data) {
//process according to data content
if (data.code == 1) {
data.count = 10;
messageBus.respond(data);
}
}
$scope.$on("$destroy", function(event) {
//before do any pending updates
messageBus.unsubscribe(name);
});
load();
});
angular.module('test')
.controller('Controller2', function($scope, messageBus) {
var name = "controller2";
function load() {
var subscriber = messageBus.subscribe(name);
subscriber.then(null, null, function(data) {
handleRequestFromService(data);
});
}
function handleRequestFromService(data) {
//process according to data content
}
$scope.getHorseCount = function() {
var promise = messageBus.request("controller1", 1, {});
promise.then(function(data) {
console.log(data.count);
});
}
$scope.$on("$destroy", function(event) {
//before do any pending updates
messageBus.unsubscribe(name);
});
load();
});