I've searched on Google but can't find information on how to do this properly. Seems like all the answers on Google are now outdated (using older versions of AngularJS).
I'm trying to setup two controllers on my AngularJS module. For example, the first controller is handling $http GET requests. And the second controller is displaying either a 'success' or 'error' message. I want to be able to call a method from the second controller with the success/error message that is to be displayed.
Or am I supposed to use a service/factory for this? I've read about services but can't figure out how to make something like this work.
var module = angular.module('app', []);
module.controller('ApiController', ['$scope', '$http', function ($scope, $http) {
$http.get('/api').
success(function(data){
// call AlertController('success')
}).
error(function(data){
// call AlertController('failed')
});
}]);
module.controller('AlertController', ['$scope', function ($scope) {
$scope.message = {
show_message: true,
type: 'info',
message: "Display message!"
};
}]);
Either doing it that way, or perhaps I would like to push the incoming alert onto a global object variable, and then remove it after it has been displayed.
Anyone know the proper way to set this up?
-
1Possible duplicate of stackoverflow.com/q/11252780/2503246Alireza Ahmadi– Alireza Ahmadi2014年09月20日 06:31:51 +00:00Commented Sep 20, 2014 at 6:31
-
Hi, Your can write on your own and inject it to your controller with module injection: angular.module('application', ['AlertModule']) After that you can use it. But there are some stuff like this github.com/Foxandxss/angular-toastr .Chrissx– Chrissx2014年09月20日 06:33:05 +00:00Commented Sep 20, 2014 at 6:33
-
1@AlirezaAhmadi - that post is over 2 years old, the code is completely different now.BuildTester1– BuildTester12014年09月20日 07:26:20 +00:00Commented Sep 20, 2014 at 7:26
-
@master994 - once I drop in the 'AlertModule', can I call the method just like AlertModule.queue("New error message!")? As for toastr, looks too complex for my use. Thanks though!BuildTester1– BuildTester12014年09月20日 07:32:17 +00:00Commented Sep 20, 2014 at 7:32
-
Yes. This is dependency injection :) Read about in this article tutorials.jenkov.com/angularjs/dependency-injection.htmlChrissx– Chrissx2014年09月21日 20:09:01 +00:00Commented Sep 21, 2014 at 20:09
2 Answers 2
Ok let's try this - you should also check out Injecting $scope into an angular service function()
The Message service:
module.service('MessageService', function ($timeout) {
var messageQueue = [];
var DISPLAY_TIME = 5000; // each message will be displayed for 5 seconds
function startTimer() {
$timeout(function() {
// Remove the first message in the queue
messageQueue.shift();
// Start timer for next message (if there is one)
if (messageQueue.length > 0) startTimer();
}, DISPLAY_TIME);
}
function add(message) {
messageQueue.push(message);
// If this is the only message in the queue you need to start the timer
if (messageQueue.length==0) startTimer();
}
function get() {
if (messageQueue.length==0) return "";
else return messageQueue[0];
}
return { add: add, get: get };
});
You can still use this ApiService as well:
module.service('ApiService', ['$http', function ($http) {
return {
get: function(url) {
return $http.get(url);
}
};
}]);
Your Search controller:
module.controller('SearchController', ['$scope', 'ApiService', 'MessageService', function ($scope, api, messages) {
api.get('/yelp').
success(function(data){
messages.add('success');
}).
error(function(data){
messages.add('failed');
});
}]);
Your Alert controller:
module.controller('AlertController', ['$scope', 'MessageService', function ($scope, messages) {
$scope.getMessage = function() { messages.get(); }
}]);
So in your html you can have:
<div ng-controller="AlertController">
<div>{{ getMessage() }}</div>
</div>
7 Comments
messageQueue.push(message); needs to be executed before startTimer() so I've swapped those 2 lines (just in case it gave you any trouble).ng-repeat statement? ie. ng-repeat="message in getMessages(), because I want getMessages() to return the entire object, instead of one message at a time. For some reason, it doesn't want to bind. AlertController calls the messages.get() on init. But after that, it doesn't update. Can I just pass the variable directly, or does it have to go through functions on each end?{{ng-show="messages().length"}} in the view, which would have been possible if I passed a json instead of a function [from the service to a $scope var in the controller]. I have a view that uses an ng-repeat="message in messages()" and I wanted to hide the entire block is there are 0 messages, but couldn't do it this way directly.here is how you make factory
module.factory('appService', ['$window', '$http', '$q', function(win, $http, $q) {
return{
backendcall: function(){
var deferred = $q.defer();
$http.get('/yelp').
success(function(data){
deferred.resolve(data);
}).
error(function(data){
deferred.resolve(status);
});
return deferred.promise;
}
}
}]);
and your controller will be like this
module.controller('AlertController', ['$scope', 'appService', function ($scope, appService) {
appService.backendcall().then(function(response){
$scope.message = {
show_message: true,
type: 'info',
message: "Display message!"
};
})
}]);
1 Comment
Explore related questions
See similar questions with these tags.