AngularJS: ng-controller по директиве не работает над включенными элементами в директиве
Здесь находится мой script:
angular.module('MyApp',[])
.directive('mySalutation',function(){
return {
restrict:'E',
scope:true,
replace:true,
transclude:true,
template:'<div>Hello<div ng-transclude></div></div>',
link:function($scope,$element,$attrs){
}
};
})
.controller('SalutationController',['$scope',function($scope){
$scope.target = "StackOverflow";
}])
и html:
<body ng-app="MyApp">
<my-salutation ng-controller="SalutationController">
<strong>{{target}}</strong>
</my-salutation>
</body>
Проблема заключается в том, что, когда SalutationController
применяется к директиве my-salutation
, $scope.target
не отображается для передаваемого элемента. Но если я помещаю элемент ng-controller
в <body>
или на элемент <strong>
, он работает. Поскольку docs говорит, ng-controller
создает новую область.
-
Кто может объяснить, как этот объем и область действия этой директивы мешают друг другу в этом случае?
-
Как установить контроллер на директиву? Любые подсказки будут оценены.
Ответы
Ответ 1
1) Задача ng-transclude
scope - это область sibling вашей директивы. Когда вы помещаете ng-controller
в родительский элемент, область, созданная ng-controller
, является родительской областью как вашей директивы, так и ng-transclude
. Из-за наследования области, transcluded элемент может привязать {{target}}
правильно.
2) Вы можете сделать это, используя пользовательский переход, чтобы связать область видимости
.directive('mySalutation',function(){
return {
restrict:'E',
scope:true,
replace:true,
transclude:true,
template:'<div>Hello<div class="transclude"></div></div>',
compile: function (element, attr, linker) {
return function (scope, element, attr) {
linker(scope, function(clone){
element.find(".transclude").append(clone); // add to DOM
});
};
}
};
})
DEMO
Или используя функцию transclude в функции ссылки:
.directive('mySalutation',function(){
return {
restrict:'E',
scope:true,
replace:true,
transclude:true,
template:'<div>Hello<div class="transclude"></div></div>',
link: function (scope, element, attr,controller, linker) {
linker(scope, function(clone){
element.find(".transclude").append(clone); // add to DOM
});
}
};
})
DEMO
Ответ 2
Чтобы иметь ту же область действия для директивы и контроллера, вы можете вызвать transcludeFn вручную:
angular.module('MyApp',[])
.directive('mySalutation',function(){
return {
restrict:'E',
scope:true,
replace:true,
transclude:true,
template:'<div>Hello<div class="trans"></div></div>',
link:function(scope, tElement, iAttrs, controller, transcludeFn){
console.log(scope.$id);
transcludeFn(scope, function cloneConnectFn(cElement) {
tElement.after(cElement);
});
}
};
})
.controller('SalutationController',['$scope',function($scope){
console.log($scope.$id);
$scope.target = "StackOverflow";
}]);
plunk
Вы можете видеть, что "003" вызывается каждый раз, и ваш код работает так, как ожидалось, с этой незначительной настройкой.