0

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?

6
  • 1
    Possible duplicate of stackoverflow.com/q/11252780/2503246 Commented 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 . Commented Sep 20, 2014 at 6:33
  • 1
    @AlirezaAhmadi - that post is over 2 years old, the code is completely different now. Commented 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! Commented Sep 20, 2014 at 7:32
  • Yes. This is dependency injection :) Read about in this article tutorials.jenkov.com/angularjs/dependency-injection.html Commented Sep 21, 2014 at 20:09

2 Answers 2

1

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>
Sign up to request clarification or add additional context in comments.

7 Comments

Hey, thanks. But I don't think this is grabbing at the root of my question. My trouble is I'm trying to separate the model from the controller, so I can use the data from that model within several controllers. ie. I want to push/save an alert messages into a model queue object from SearchController, then pull/read those messages from within AlertController, so that AlertController can update/display the alerts (and ie. after 5 seconds, hide the alerts one-by-one, and then update/delete the messages queue to clear the old message). But not sure how to setup a service to act as this model.
Perfect! Exactly what I needed to see. Thank you so much! 1. Didn't understand why services used the return{} but now I see how it works. 2. Didn't know a view could use call a function for output.
No probs - I just noticed that messageQueue.push(message); needs to be executed before startTimer() so I've swapped those 2 lines (just in case it gave you any trouble).
I got a display issue. How do I use getMessage() in an 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?
I got it working. The one downside is I can't do {{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.
|
0

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

That's really confusing. Can you explain what's going on in your code?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.