0

Я создаю настраиваемую директиву, которая наследует область действия родительского контроллера. По большей части я могу получить доступ к объекту «scope» директивы, который я установил в «$ scope» контроллера, за исключением свойств, которые я установил в $ http.get. Независимо от того, пришли ли эти свойства из API или были просто определены буквально, это не имеет значения.

Для меня очень странно, что если я просто зарегистрирую «область видимости» директивы, я могу определенно увидеть свойства, заданные $ http.get, но если я попытаюсь получить к ним доступ напрямую, они не определены.

Я могу получить доступ ко всему в представлении HTML отлично.

var myApp = angular.module('myApp'); 

myApp.controller('getData', function($scope, $http) { 
    var myData='myData.json'; 
    $scope.helloFromController = "Hello! This is the controller!"; 
    $scope.getTheData = function() { 
    $http.get(myData). 
     success(function(data, status) { 
     $scope.helloFromHttp = "Hello! This is the http!"; 
     }); 
    }; 
    $scope.getTheData(); 
}); 

myApp.directive('useData', function ($parse) { 
    var directiveObj = { 
    link: function (scope, element, attrs) { 
     console.log(scope); 
     // Returns the scope object that clearly includes the helloFromController and helloFromControllerHttp properties 
     console.log(scope.helloFromController); 
     // returns "Hello! This is the controller!" 
     console.log(scope.helloFromHttp) 
     // returns undefined 
    } 
    }; 
    return directiveObj; 
}); 

Похоже, что есть что-то о том, как работает $ scope с $ http, который я не понимаю. Помощь приветствуется.

+1

Это не о $ scope, это просто факт, что ajax асинхронен. – dfsq

ответ

0

Ваша директива разделяет ту же область действия контроллера. Функция ссылки вашей директивы загружается, когда директива находится в вашем шаблоне. $scope.helloFromController - это просто строка. Итак, вы видите это, войдя в консоль. Но, $scope.helloFromHttp устанавливается после того, как обещание разрешено для $http. Таким образом, вы не видите значение моментально как console.log(scope.helloFromHttp), прежде чем оно будет установлено в контроллере. Вы можете попробовать использовать $ timeout, чтобы увидеть измененное значение scope.helloFromHttp.

myApp.directive('useData', function ($parse, $timeout) { 
    var directiveObj = { 
    link: function (scope, element, attrs) { 
     // Returns the scope object that clearly includes the helloFromController and helloFromControllerHttp properties 
     console.log(scope); 

     // returns "Hello! This is the controller!" 
     console.log(scope.helloFromController); 

     // returns undefined 
     console.log(scope.helloFromHttp) 

     // set $timeout to trigger after 10 sec, you can reduce or increase the time 
     $timeout(function() { 
     console.log(scope.helloFromHttp); 
     }, 10000) 
    } 
    }; 
    return directiveObj; 
}); 

Надеюсь, это поможет.

+0

Так что это работает, но это похоже на плохую практику. Есть ли более разумный способ привязки данных из $ http.get к директиве? –

+0

Как я уже сказал, 'scope.helloFromHttp' в области директивы будет обновляться, так как область полномочий такая же, как и область контроллера. Не имеет никакого отношения к привязке. Но да, если вы хотите что-то сделать в функции директивной ссылки после того, как 'scope.helloFromHttp' обновляется через' $ http', вы можете '$ смотреть 'переменную в функции директивной ссылки. – Saad

+0

Это на самом деле то, что я только что сделал. Я использовал $ watch »и включил условие, чтобы увидеть, существует ли scope.helloFromHttp. Это отлично работает. Спасибо за вашу помощь! –

1

Функция связывания выполняется до вызова обратного вызова из асинхронного HTTP-вызова.

Пример кода: http://jsfiddle.net/k54ubb9L/

<div ng-controller="MyCtrl" use-data> 
    Hello, {{ userData.username }}! 
</div> 


var myApp = angular.module('myApp', []); 

myApp.controller('MyCtrl', function($scope, $http) { 

    function getTheData() { 
    $http.get("http://jsonplaceholder.typicode.com/users/1"). 
    success(function(response, status) { 
     $scope.userData = response; 
    }); 
    }; 

    getTheData(); 
}); 

myApp.directive('useData', function($parse) { 
    return { 
    link: function(scope, element, attrs) { 
     scope.$watch("userData", function(newValue, oldValue) { 
     console.log(newValue, oldValue); 
     }); 
    }, 
    restrict: "A" 
    }; 
}); 
0

На самом деле ваш код хорошо без каких-либо изменений работы; проблема заключается в том, что вы отобразили его в консоли, но если вы отобразите его в HTML, он будет обновляться, как ожидалось. Вот пример: http://plnkr.co/edit/WrqO7FeF5d5JdVas9jiL?p=preview

directive('useData', function($parse) { 
    return { 
    template: "From directive: {{helloFromHttp}}", 
    link: function(scope, element, attrs) { 

     console.log(scope); 
     // Returns the scope object that clearly includes the helloFromController and helloFromControllerHttp properties 
     console.log(scope.helloFromController); 
     // returns "Hello! This is the controller!" 
     console.log(scope.helloFromHttp); 
     // returns undefined 
    } 
    }; 
}); 
Смежные вопросы