Я пытаюсь взять id из области $ scope контроллера представления и передать его моей директиве, которая затем делает еще несколько http-вызовов, используя этот идентификатор.
Здесь мой контроллер и директива js:
app.controller('MainCtrl', function(postsFactory) {
_this = this;
postsFactory.get({ id: $state.params.id}).$promise.then(function(res){
//assign the response to this controller as a post and
//output the controller on the view as editPostCtrl.
_this.post = res;
_this.idOfPost = _this.post.id;
// the post.id does exist
});
});
app.directive('foo', function() {
return {
restrict: 'E',
scope: {
postId: '=postId',
},
controller: function($scope) {
//make some more http calls with the postId
},
link: function(scope, element, attr) {
scope.$watch('postId', function(newVal) {
if(newVal) { postId = newVal;}
});
}
};
});
Вид:
<body ng-controller="MainCtrl as mainCtrl">
<foo post-id="mainCtrl.idOfPost"></foo>
</body>
Идентификатор никогда не делает это для представления. Когда я проверяю элемент и смотрю на атрибут директивы, я вижу
пост-ID = "mainCtrl.idOfPost"
Поскольку я звоню, чтобы получить идентификатор в главном контроллере представления и привязать его к контроллеру, используя синтаксис "ctrl as", я увидел, что мне нужно следить за ним в директиве, потому что главный контроллер представления вернет обещание: см. это для ref: указана директива перед тем, как обетование будет разрешено
Ну, это не сработало для меня. Тем не менее, я нашел, что использование метода watch, а также обертывание директивы в ng-if будет работать:
<div ng-if="main.idOfPost">
<foo post-id="mainCtrl.idOfPost" ></foo>
</div>
Однако, кажется, нет необходимости иметь логику в представлении, подобном этому, и делает директиву труднее использовать. Я просто не уверен, как его разрешить в js. Любые предложения приветствуются.
Единственный, который подошел достаточно близко для меня, - это предложение @Paul147. Однако у меня также был фильтр, который применяла директива, и это вызвало более глубокие проблемы, которые действительно трудно было понять. Поэтому я решил совершенно новый вариант, разрешив данные до загрузки представлений через ui-router. Работает как шарм сейчас и нет $ watch!
Здесь, где я его поднял. https://scotch.io/tutorials/making-skinny-angularjs-controllers
Я бы включил в ваш контроллер значение init вашего idOfPost
_this.idOfPost = '';
И функция $ watch в вашей директивной ссылке должна иметь 1-й параметр, функция, возвращающая переменную, которую вы хотите посмотреть:
link: function(scope, element, attr) {
scope.$watch(
function() { return scope.postId;},
function(newVal,oldValue) {
if(newVal!==oldValue) { postId = newVal; }
});
У меня были проблемы, похожие на это. Попробуйте использовать ваши $ watch с функцией, чтобы вернуть значение области
scope.$watch(function(){
return scope.postId;
}, function(){ //whatever });
Возможно, что после выполнения $ prom после привязок это может вызвать проблемы с директивой. Если это не работает, загрузите пример в Plunker, и я посмотрю.
Кроме того, я думаю, что вы должны интерполировать свои значения директивы с двойными фигурами
<foo post-id="{{mainCtrl.idOfPost}}"></foo>
в отличие от
<foo post-id="mainCtrl.idOfPost"></foo>
Надеюсь это поможет
То, что вам может потребоваться, - это реализовать $scope.$watch
в controller
директивы, а не link
, а затем устранить любые дополнительные HTTP-вызовы, которые вам нужно будет сделать внутри этого обратного вызова.
Здесь plnkr с базовой настройкой: http://plnkr.co/edit/pUybxobHYI6vvjd0M5ON?p=preview
$scope.idOfPost
непосредственно в своей директиве, не передавая ее?