Директива дается до того, как обещание будет выполнено
У меня возникли проблемы с получением моей директивы для отображения его содержимого только после того, как мое обещание было выполнено. я думал then()
должен был сделать это, но это, похоже, не работает..
Вот мой контроллер:
// Generated by CoffeeScript 1.6.3
(function() {
var sprangularControllers;
sprangularControllers = angular.module('sprangularControllers', ['sprangularServices', 'ngRoute']);
sprangularControllers.controller('productsController', [
'$scope', '$route', '$routeParams', 'Product', 'Taxonomy', function($scope, $route, $routeParams, Product, Taxonomy) {
Taxonomy.taxonomies_with_meta().$promise.then(function(response) {
return $scope.taxonomies = response.taxonomies;
});
return Product.find($routeParams.id).$promise.then(function(response) {
return $scope.currentProduct = response;
});
}
]);
}).call(this);
Моя директива:
// Generated by CoffeeScript 1.6.3
(function() {
var sprangularDirectives;
sprangularDirectives = angular.module('sprangularDirectives', []);
sprangularDirectives.directive('productDirective', function() {
return {
scope: {
product: '='
},
templateUrl: 'partials/product/_product.html',
link: function(scope, el, attrs) {
console.log(scope);
console.log(scope.product);
return el.text(scope.product.name);
}
};
});
}).call(this);
Scope возвращается нормально, и когда я проверяю это в dev tools scope.product
не является неопределенным, однако я предполагаю, что это потому, что, когда я проверяю это, обещание было выполнено?
console.log(scope.product)
однако возвращает неопределенное..
4 ответа
Поскольку ваше значение заполняется асинхронно, вам нужно добавить функцию наблюдения, которая обновляет связанный элемент.
link: function(scope, el, attrs) {
scope.$watch('product', function(newVal) {
if(newVal) { el.text(scope.product.name);}
}, true);
}
Вы также можете перенести много сложностей в контроллер директив и использовать функцию link только для манипулирования DOM.
true
третий параметр $watch
вызывает глубокое наблюдение, так как вы привязываете эту директиву к модели.
Вот несколько ссылок с хорошими примерами:
http://www.ng-newsletter.com/posts/directives.html
http://seanhess.github.io/2013/10/14/angularjs-directive-design.html
Как было сказано в официальной ветке об этой проблеме (быстро закрывающейся как "не будет исправлено, потому что это заставит директивы ждать"), обходной путь - обернуть вашу директиву в ng-if
:
<div ng-if="myPromiseParam">
<my-directive param="myPromiseParam">
</div>
Я знаю, что это старый вопрос, но подумал, что попробую дать обновленный ответ.
При использовании маршрутизатора и ui-router, и ngRouter имеют методы разрешения, которые разрешают обещания при изменении URL-адреса перед переключением на этот маршрут и отображением данных на странице.
ngRouter Разрешить учебник
UI-роутер Разрешить документы
Другой вариант, вместо использования $watch
это использовать угловые $q
библиотека обещаний. Более конкретно, $q.when()
метод. Это принимает обещания и ценности. Если это обещание, оно уволит .then()
когда обещание разрешается. Если это значение, оно оборачивает его в обещание и немедленно разрешает.
link: function(scope, el, attrs){
$q.when(scope.product).then(function(product){
scope.product = product;
el.text(scope.product.name);
});
}
Или есть пара способов, которыми вы ничего не можете показать только с помощью HTML.
<product-directive product='object'>
<!-- Will hide span until product.name exists -->
<span ng-show='product.name'>{{ product.name }}</span>
<!-- Will show default text until key exists -->
{{ product.name || 'Nothing to see here' }}
<!-- Will show nothing until key exists -->
<span ng-bind='product.name'></span>
</product-directive>
Используйте $watch для вашей переменной в вашей директиве, чтобы получить обновленное значение вашей переменной.
Вы также можете использовать $q для разрешения обещания.