0

I'm new to angular and I'm facing some problems...

I have two directives that share the same controller and that controller was one service requesting a json file on a async call ($http).

The directives need the same data and both are init almost at the same time, but I want only to make one call and retrieve the data to the controllers and update the view with the data.

MainMenuHeader.js

(function () {
var app = angular.module("mainMenuHeaderModule", ["mainMenuControllerModule"]);

app.directive("mainheader", function () {
    return {
        restrict: "A",
        transclude: true,
        templateUrl: "TMainMenuHeader.html",
        controller: "mainMenuController",
    }
});})();

MainMenuAside.js

(function () {
var app = angular.module("mainMenuAsideModule", ["mainMenuControllerModule"]);

app.directive("mainaside", function () {
    return {
        restrict: "A",
        transclude: true,
        templateUrl: "TMainMenuAside.html",
        controller: "mainMenuController"
    }
});})();

MainMenuController.js

        (function () {
        var app = angular.module("mainMenuControllerModule", ["mainMenuServiceModule"]);

        app.controller("mainMenuController", ["$scope", "MainMenuService",
            function ($scope, MainMenuService)
            {

                $scope.menuList = MainMenuService.GetAsyncData();

                console.log("mainMenuController menuList: " + $scope.menuList);
        }]);
    })
();

MainMenuService.js

    (function () {
    var module = angular.module("mainMenuServiceModule", []);

    module.factory("MainMenuService", ["$q", "$http", function ($q, $http)
    {
        var data;

        var getAsyncData = function()
        {
            console.log(" -> getting data...");
            $http.get("menu.json")
            .success(function(result)
            {
                data = result;

                console.log("async data: " + data);
            });

             return data;
        }


        var getDataObject = function ()
        {
            return [
                        {
                            id:1,
                            title: "Menu 1",
                            submenus: [
                                {
                                    title: "Sub Menu 1",
                                    itens: [
                                        { title: "Option 1" },
                                        { title: "Option 2" },
                                        { title: "Option 3" }
                                    ]
                                }
                            ]
                        },
                        {
                            id:2,
                            title: "Menu 2",
                            submenus: [
                                {
                                    title: "Sub Menu 2",
                                    itens: [
                                        { title: "Option 1" },
                                        { title: "Option 2" },
                                        { title: "Option 3" },
                                        { title: "Option 4" },
                                        { title: "Option 5" }
                                    ]
                                }
                            ]
                        },
                        {
                            id:3,
                            title: "Menu 3",
                            submenus: [
                                {
                                    title: "Sub Menu 3",
                                    itens: [
                                        { title: "Option 1" },
                                        { title: "Option 2" },
                                        { title: "Option 3" }
                                    ]
                                }
                            ]
                        }
                    ];
        }

        return {
            GetDataObject : function()
            {
                return getDataObject();
            },

            GetAsyncData : function()
            {
                return getAsyncData();
            }
        }
    }]);
})();

The service was two methods. One that return an JS object just for testing, and another with a $http request that is not working.

I also tried return a deferred from the service and wait on the controller for the response, but with out success, maybe I made something wrong... can someone help me out?

I also made a plunker so you see the problem in action...

http://plnkr.co/edit/7NIPeAsUYlh96p3hUij7

Thank you for your time... =)

2 Answers 2

1

good thing you created a plunker.

The problem was in this function of the service:

var data;
var getAsyncData = function()
{
    console.log(" -> getting data...");
    $http.get("menu.json")
    .success(function(result)
    {
        data = result;

        console.log("async data: " + data);
    });

     return data;
}

basically you're returning an undefined variable to the controller, then make the http request and when you get the response you update data to reference the result, but the in the controller $scope.menuList still points to undefined (you're not updating the returned object from the function).

to fix it you have 2 options:

to bind the view to a property of the object that you return in the service and then update the object property when you get the response from the http call. here's the relevant plunker

other option is that for the async call the in the service you return a promise and once the promise is resolved the controller can update the scope with the result of the request. here's the relevant plunker

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you!!! =D Both solutions worked on my main project! I choose the first one. That way, I think I can have a concept of a model inside the service and change the data there, leaving the controller for other stuff...
0

I changed a bit my service... if a another request is made while another is running the reference of data is returned, and everyone who is calling will be update when finished:

module.factory("MainMenuService", ["$http", function ($http)
{
    var isRequesting = false;
    var data = {};

    var getAsyncData = function()
    {
        if (isRequesting) return data;

        isRequesting = true;

        console.log(" -> getting async data...");
        $http.get("json/mainMenu.json")
        .success(function (result)
        {
            isRequesting = false;

            angular.forEach(result, function (value, key)
            {
                value.id = key;
                switch(value.submenus.length)
                {
                    case 1: value.columnsSize = 12; break;
                    case 2: value.columnsSize = 6; break;
                    default: value.columnsSize = 4; break;
                } 
            })

            data.menuList = result;

            console.log(" -> data.menuList : " + data.menuList);
        });

        return data;
    }

    return {
        GetAsyncData: function ()
        {
            return getAsyncData();
        }
    }
}]);

Comments

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.