0

This is a relatively simple piece of code that calls a service and returns some data. I need to set the $scope with the result of the data. Is there an easy way to set this data to the scope without resorting to to binding the scope to the function in the then clause?

Angular Code

(function () {
    var app = angular.module('reports', []);
    var reportService = function($http, $q) {
        var service = {};
        service.getMenuData = function() {
            var deffered = $q.defer();
            $http.get('/Report/MenuData').success(function(data) {
                deffered.resolve(data);
            }).error(function(data) {
                deferred.reject("Error getting data");
            });
            return deffered.promise;
        }
        return service;
    };
    reportService.$inject = ['$http', '$q'];
    app.factory('reportService', reportService);

    var reportMenuController =
        function ($scope, $http, reportService) {
            $scope.getMenuData = function(e) {
                reportService.getMenuData().then(function(data) {
                    // Need to set the $scope in here
                    // However, the '$scope' is out of scope
                });
            }
        };
    reportMenuController.$inject = ['$scope', '$http', 'reportService'];
    app.controller('ReportMenuController', reportMenuController);
})();

Markup

<div>
    <div ng-controller="ReportMenuController">
        <button ng-click="getMenuData()">Load Data</button>
    </div>
</div>
jwize
  • 4,230
  • 1
  • 33
  • 51
  • 1
    $scope should be defined. Here's a plunker with your example: https://plnkr.co/edit/2Ozy4YmjtVEXYXzKtRQk?p=preview – boyomarinov Jan 21 '16 at 10:42
  • 1
    http://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it – Benjamin Gruenbaum Jan 21 '16 at 11:20
  • Okay, I didn't see the small detail there in the Plunker. – jwize Jan 22 '16 at 04:53
  • @Benjamin Gruenbaum. I definitely want to avoid the Anti-Pattern. I am not clear on how to do that. I will spend some more time with that post but it seems to be allot take in from the given post as I am new to this domain. – jwize Jan 22 '16 at 05:03
  • @jwize, see my answer. I show you there, how to avoid explicit promise construction. – lex82 Jan 22 '16 at 07:18

2 Answers2

1

There is absolutely no problem to set the $scope from within the function passed to then(). The variable is available from the enclosing scope and you can set your menu data to one of its fields.

By the way: You should consider to use then() instead of success() for your http request. The code looks much nicer because then() returns a promise:

service.getMenuData = function() {
    return $http.get('/Report/MenuData').then(function(response) {
        return response.data;
    }, function(response) {
        deferred.reject("Error getting data");
    });
}

success() is deprecated by now.

lex82
  • 11,173
  • 2
  • 44
  • 69
  • This doesn't solve the problem but is a way to improve the code. The function hoisting that was in boyomarinov's post was the missing piece. And you mentioned the reason (Hoisting) for its validity. – jwize Jan 22 '16 at 21:40
0

I didn't notice the small detail missing in the plunker where my code was different.

(function () {

...

    var reportMenuController =
        function ($scope, $http, reportService) {

        $scope.getMenuData = getMenuData;
        function getMenuData(e) {
                reportService.getMenuData().then(function(data) {
                    // Now I have access to $scope
                });
            }
        };
  ...
})();

Notice the changes to the two lines as below:

$scope.getMenuData = getMenuData;

function getMenuData(e) {

This also begs a small question which is, "Why is it okay to set getMenuData to the $scope before it is declared?

jwize
  • 4,230
  • 1
  • 33
  • 51
  • This is called 'hoisting': http://www.w3schools.com/js/js_hoisting.asp It applies to function declarations as well. – lex82 Jan 22 '16 at 07:16
  • Did I answer your main question, or is anything unclear? By the way, you shoud rather have posted this "answer" as another question. It does not answer your original question and is a completely different question. – lex82 Jan 22 '16 at 07:19
  • After reading that it seems that $scope.getMenuData should = undefined. I will read it again. I read http://adripofjavascript.com/blog/drips/variable-and-function-hoisting which is clear for function hoisting. – jwize Jan 22 '16 at 21:35