Директива AngularJS не получает данные

У меня есть служба, которая получает данные с сервера и отправляет их контроллеру:

Услуга:

publicApp.angularModule.factory('resultService', function ($http) {
        return {
            getResult: function() {
                return $http.get("/Result/GetResult")
                    .success(function(result) {
                        return result.data;
                    }).error(function(result) {
                        console.log("error" + result);
                    });
            },
        };
    });

Контроллер:

publicApp.angularModule.controller('PublicResultCtrl', function ($scope, $location, resultService) {

    resultService.getResult().then(function (resultResponse) {
        $scope.data = resultResponse.data;
        $scope.graph = [];

        _.forEach($scope.data.TreningExerciseScores, function(item) {
            $scope.graph.push(addDataToGraph(item.Item2, item.Item1));
        });

    });

    var addDataToGraph = function (num, text) {
        return {
            y: num,
            legendText: text,
        };
    };

});

И у меня есть директива, которая должна получать данные от контроллера. Я называю директиву так:

<div id="graph" style="width: 200px; height: 200px" canvasjs graphData="graph"></div> 

И вот моя директива:

publicApp.angularModule.directive('canvasjs', function () {


    return {
        restrict: 'A',
        scope: {data : '=graphData'} ,
        link: function (scope, element, attrs) {

            scope.$watch('data', function (data) {
                    console.log(scope.data);

            });         
        }
    };
});

Но scope.data не определен. Я знаю, что $ http.get - это асинхронная операция, но не должна ограничиваться. $ Watch получать обновления?


person hyperN    schedule 22.10.2013    source источник


Ответы (3)


Попробуйте передать значение директиве как: canvasjs="graph".

В моем примере я имитирую ответ от службы и возвращаю обещание.

HTML

<div ng-controller="fessCntrl">
    <div id="graph" style="width: 200px; height: 200px" canvasjs="graph"></div>
    <pre>   graph:  {{graph|json}}  </pre>
    <pre>   data:  {{data|json}}  </pre>  
</div>

JS

var fessmodule = angular.module('myModule', ['ngResource']);

fessmodule.controller('fessCntrl', function ($scope, resultService) {

    resultService.getResult().then(function (resultResponse) {
        console.log(resultResponse);

        $scope.data = resultResponse.data;
        $scope.graph = [];

        angular.forEach($scope.data.TreningExerciseScores, function (item, key) {
            $scope.graph.push(addDataToGraph(item.Item2, item.Item1));
        });


    });

    var addDataToGraph = function (num, text) {
        return {
            y: num,
            legendText: text,
        };
    };

});

fessmodule.$inject = ['$scope', 'Data'];

fessmodule.directive('canvasjs', function () {
    return {
        restrict: 'A',

        link: function (scope, element, attrs) {

            scope.$watch('data', function (data) {
                console.log("fff", scope.data);

            });
        }
    };
});

fessmodule.factory('resultService', ['$resource', '$q', function ($resource, $q) {
    var input = {
        data: {
            TreningExerciseScores: [{
                Item1: "aaa"
            },
            {
                Item2: "bbb"
            }]
        }
    };

    var factory = {
        getResult: function (selectedSubject) {
            var deferred = $q.defer();

            deferred.resolve(input);

            return deferred.promise;
        }

    }
    return factory;
}]);

Демо Fiddle

person Maxim Shoustin    schedule 22.10.2013
comment
@hyperN см. мой ответ и демо. - person Maxim Shoustin; 22.10.2013

Если вы собираетесь обрабатывать обещание в своем контроллере:

resultService.getResult().then(function (resultResponse) {
        $scope.data = resultResponse.data;
        $scope.graph = [];

        _.forEach($scope.data.TreningExerciseScores, function(item) {
            $scope.graph.push(addDataToGraph(item.Item2, item.Item1));
        });

    });

Нет необходимости обрабатывать это в вашем сервисе:

getResult: function() {
                return $http.get("/Result/GetResult");
            },

Если вы хотите обработать только ошибку в службе, вам нужно снова обернуть обещание. Для этого можно использовать $q.when:

getResult: function() {
                return $http.get("/Result/GetResult")
                    .success(function(result) {
                        return $q.when(result.data);
                    }).error(function(result) {
                        // not sure what you want to do here
                        console.log("error" + result);
                        return $q.when(result);

                    });
            },

$q.when обернет объект обещанием, если это еще не обещание.

person Davin Tryon    schedule 22.10.2013
comment
Спасибо за предложения, я изменил свой код в соответствии с ними, но по-прежнему scope.data не определен - person hyperN; 22.10.2013
comment
Может быть нужно вернуть $q.when(result), а не result.data. В противном случае вы делаете result.data.data. - person Davin Tryon; 22.10.2013
comment
Я зарегистрировал $ scope.graph, и там все было хорошо, так что это не проблема с моей службой, я считаю, что проблема в директиве - person hyperN; 22.10.2013
comment
Куда вы заходите? Попробуйте записать результат в ваш resultService и ваш контроллер. Посмотрите, видите ли вы свойство data на обоих. - person Davin Tryon; 22.10.2013
comment
Вы были правы, result.data в resultService было undefined, и result был объектом, а в контроллере все было в порядке - person hyperN; 22.10.2013
comment
Но в директиве это все еще не определено - person hyperN; 22.10.2013

Вы не можете вернуть данные в обработчике success() и ожидать, что они вернутся. Вам нужно связать другое обещание (return defer.promise()) или выполнить success в вашем контроллере и изменить $ scope в вашем результате. Или просто верните весь вызов $http, который уже является обещанием.

person Jonathan Rowny    schedule 22.10.2013