6

Problem polega na tym, że dyrektywa child wiąże się z rodzicem, jednak składnia {{name}} zostaje zignorowana przez ng-repeat. Jaka byłaby właściwa droga do osiągnięcia tego?Dyrektywa kątowa/dyrektywa child transclude inside ng-repeat

HTML (Główny dyrektywa/dziecko)

<compact-select 
    no-item-selected-text="Add a Customer" 
    no-item-selected-icon="fa-user" 
    search-placeholder="Type a customer name" 
    cs-model="customer" 
    cs-items="contacts" 
> 
    <display-item-template> 
     <span>{{name}}</span> 
     or 
     <span>{{item.name}}</span> 
    </display-item-template> 
</compact-select> 

dyrektywa

angular.module('core').directive('compactSelect', [function($timeout) { 
    return { 
     templateUrl : 'modules/core/views/components/compact-select-tpl.html', 
     bindToController: true, 
     transclude: true, 
     scope: { 
      noItemSelectedText: '@', 
      noItemSelectedIcon: '@', 
      csModel: '=', 
      csItems: '=csItems' 
     }, 
     controllerAs : 'ctrl', 
     controller : function($scope) { 

     } 
    }; 
}]).directive('displayItemTemplate', function($timeout) { 
    return { 
     require: '^compactSelect', 
     restrict: 'E' 
    } 
}); 

dyrektywa szablonu (moduły/rdzeń/views/components/compact-select-tpl.html)

<div class="compact-select-repeater-box" style="" > 
    <div ng-transclude ng-repeat="item in ctrl.csItems | filter:searchParam" class="compact-select-repeater" ng-class="ctrl.getHighlightedClass(item)" ng-click="ctrl.itemSelected(item)"> 
     <span>{{item.name}}</span> 
     <span>{{item.id}}</span> 
    </div> 
    <div style="position:absolute;bottom:0"> 
     <a href="#">+ Click here to add customer {{ctrl.message}}</a> 
    </div> 
</div> 

widzę, że

<span>{{item.name}}</span> 
<span>{{item.id}}</span> 

pobiera zastąpione

<span></span> 
or 
<span>{{item.name}}</span> 

a nie

<span>{{name}}</span> 
or 
<span>{{item.name}}</span> 

Pytanie: Jak uzyskać ng-repeat dla przestrzegania składni powiązań html z dyrektywą potomną? Czy istnieje inny sposób, aby to osiągnąć?

Odpowiedz

8

Jeśli się nie mylę, próbujesz utworzyć list view w taki sposób, że użytkownik dostarczyłby template z listy, ale metody (kliknięcie itp.) zostałyby już udostępnione w dyrektywie.

Teraz, ponieważ angular 1.3 The transcluded scope jest dzieckiem directive isolated scope,

tak, w przypadku, jeśli się prawidłową hierarchię, można uzyskać dostęp do directive scope od wewnątrz szablonu dostarczonego przez użytkownika.

Oto twoja hierarchia zakres:

Directive isolated scope ->ng-repeat new scope for every row ->transcluded scope.

więc, jeśli chcesz uzyskać dostęp do directive scope z transcluded scope, ty musiałby zrobić $parent (dla NG-repeat), a następnie uzyskać dostęp item.name, jak poniżej:

<display-item-template>    
     <span>Item Name: {{$parent.item.name}}</span>    
</display-item-template> 

Ponadto nie robić potrzeba powiązania wewnątrz compact-select-tpl, ponieważ chcesz, aby zawartość pochodzić z transkluzji:

<div class="compact-select-repeater-box" style="" > 

    <div ng-transclude ng-repeat="item in ctrl.csItems | filter:searchParam" 
    class="compact-select-repeater" 
    ng-class="ctrl.getHighlightedClass(item)" 
    ng-click="ctrl.itemSelected(item)"> 
     <!-- <span>{{item.name}}</span> 
     <span>{{item.id}}</span> --> 
    </div> 

    <div style="position:absolute;bottom:0"> 
     <a href="#">+ Click here to add customer {{ctrl.message}}</a> 
    </div> 
</div> 
+0

wow ... to jest niesamowite działa dobrze. Dziękuję za wyjaśnienie cyklu życia dyrektywy. – Tim

2

Dyrektywa displayItemTemplate, którą transkludujesz wewnątrz innej dyrektywy, ma już interpolację danych: {{name}} i {{item.name}}.

Jeśli nie posiadasz tych zmiennych w polu $ zakres, to transkluduje puste ciągi w twoich rozpiętościach.

Następnie w dyrektywie compactSelect element div, który zostanie dołączony, spowoduje, że jego zawartość zostanie zastąpiona.

Jeśli przeniesiesz dyrektywę displayItemTemplate do szablonu innej dyrektywy, powtórzenie zadziała. (Trzeba będzie usunąć ng (transclude i transclude. Prawda

Fiddle

Dodatkowo, jeśli używasz bindToController, nie umieścić atrybuty wewnątrz zakresu

function compactSelect() { 
 
    return { 
 
    template : [ 
 
     '<div class="compact-select-repeater-box" style="" >', 
 
     '<div ng-repeat="item in ctrl.csItems | filter:searchParam" class="compact-select-repeater" ng-class="ctrl.getHighlightedClass(item)" ng-click="ctrl.itemSelected(item)">', 
 
     '<display-item-template>', 
 
      '<span>{{item.name}}</span>', 
 
     '</display-item-template>', 
 
     '</div>', 
 
     '<div style="position:absolute;bottom:0">', 
 
      '<a href="#">+ Click here to add customer {{ctrl.message}}</a></div></div>', 
 
    ].join(''), 
 
    bindToController: { 
 
     noItemSelectedText: '@', 
 
     noItemSelectedIcon: '@', 
 
     csItems: '=csItems' 
 
    }, 
 
    scope: {}, 
 
    controllerAs : 'ctrl', 
 
    controller : function($scope) { 
 

 
    } 
 
    } 
 
} 
 
function displayItemTemplate() { 
 
    return { 
 
     require: '^compactSelect', 
 
     restrict: 'E' 
 
    } 
 
} 
 
function SuperController() { 
 
\t this.name = "a name"; 
 
\t this.contacts = [{name:"rob"}, {name:"jules"}, {name:"blair"}]; 
 
} 
 
angular.module('myApp', []); 
 
angular 
 
    .module('myApp') 
 
    .controller('SuperController', SuperController) 
 
    .directive('compactSelect', compactSelect) 
 
    .directive('displayItemTemplate', displayItemTemplate);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script> 
 
<div ng-app="myApp"> 
 
    <div ng-controller="SuperController as s"> 
 
    <compact-select 
 
     no-item-selected-text="Add a Customer" 
 
     no-item-selected-icon="fa-user" 
 
     search-placeholder="Type a customer name" 
 
     cs-items="s.contacts"> 
 
    </compact-select> 
 
    </div> 
 
</div>

+0

Dzięki widzę, gdzie idziesz z tym, ale nie to co próbuję achive. – Tim