AngularJS: ng-controller on directive nie działa na elementach transkludowanych w ramach dyrektywy

Tutaj jest mój skrypt:

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";
}])

I html:

<body ng-app="MyApp">
    <my-salutation ng-controller="SalutationController">
        <strong>{{target}}</strong>        
    </my-salutation>
</body>

Problem polega na tym, że gdy SalutationController zostanie zastosowana do my-salutation dyrektywy, $scope.target nie jest widoczny dla elementu transkludowanego.Ale jeśli umieszczę ng-controller na <body> lub na <strong> element, to działa. Jak mówi docs, ng-controller tworzy nowy zakres.

  • Kto może wyjaśnić, w jaki sposób ten zakres i zakres dyrektywy zakłócają się wzajemnie w tym przypadku?

  • Jak mogę umieścić kontroler w sprawie dyrektywy? Wszelkie wskazówki będą mile widziane.

Author: John Slegers, 2014-03-22

2 answers

1) problem polega na tym, że zakres ng-transclude jest zakresem Twojej dyrektywy. Gdy umieścisz ng-controller do elementu nadrzędnego, zakres utworzony przez ng-controller jest nadrzędnym zakresem zarówno Twojej dyrektywy, jak i ng-transclude. Ze względu na dziedziczenie zakresu, element transkludowany jest w stanie poprawnie powiązać {{target}}.

2) możesz to zrobić za pomocą niestandardowej transcluzji, aby samodzielnie powiązać zakres

.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

Lub za pomocą funkcji transclude w linku funkcja:

.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

 9
Author: Khanh TO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-22 09:22:51

Aby mieć ten sam zakres dla dyrektywy i kontrolera, można wywołać trancludefn ręcznie:

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

Możesz zobaczyć, że '003' jest wylogowany za każdym razem, a Twój kod działa zgodnie z oczekiwaniami z tą drobną korektą.

 2
Author: Oleg Belousov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-22 09:16:40