Angular directive/child 指令嵌入在 ng-repeat 中
Angular directive/child directive transclude inside ng-repeat
问题是子指令绑定到父指令,但是语法 {{name}}
被 ng-repeat
忽略。实现这一目标的正确方法是什么?
HTML(Main/child 指令)
<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>
指令
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'
}
});
指令模板(modules/core/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>
我可以看到
<span>{{item.name}}</span>
<span>{{item.id}}</span>
被替换为
<span></span>
or
<span>{{item.name}}</span>
而不是
<span>{{name}}</span>
or
<span>{{item.name}}</span>
问题: 如何让 ng-repeat
遵守来自子指令的 html 绑定语法?还是有另一种方法可以实现这一目标?
您在其他指令中嵌入的 displayItemTemplate
指令已经插入了数据 {{name}}
和 {{item.name}}
.
如果您在 $scope 中没有这些变量,它将在您的范围内嵌入空字符串。
然后在您的 compactSelect
指令中,被嵌入的 div 的内容将被覆盖。
如果您将 displayItemTemplate
指令移动到另一个指令的模板中,重复将起作用。 (您需要删除 ng(transclude 和 transclude: true
此外,如果您使用 bindToController
,请不要将属性放在范围内。
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() {
this.name = "a name";
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>
如果我没记错的话,那么您正在尝试创建一个 list view
,这样列表的 template
将由用户提供,但是方法(点击等)将已经通过指令提供。
现在,由于 angular 1.3
,transcluded scope
是 directive isolated scope
、
的子项
因此,在您的情况下,如果您遵循正确的层次结构,则可以从用户提供的模板中访问 directive scope
。
这是您的范围层次结构:
Directive isolated scope
--> ng-repeat new scope for every row
--> transcluded scope
.
所以,如果您想从 transcluded scope
访问 directive scope
,
您需要执行 $parent
(对于 ng-repeat)然后访问 item.name
,如下所示:
<display-item-template>
<span>Item Name: {{$parent.item.name}}</span>
</display-item-template>
此外,您不需要 compact-select-tpl
中的绑定,因为您希望该内容来自嵌入:
<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>
问题是子指令绑定到父指令,但是语法 {{name}}
被 ng-repeat
忽略。实现这一目标的正确方法是什么?
HTML(Main/child 指令)
<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>
指令
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'
}
});
指令模板(modules/core/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>
我可以看到
<span>{{item.name}}</span>
<span>{{item.id}}</span>
被替换为
<span></span>
or
<span>{{item.name}}</span>
而不是
<span>{{name}}</span>
or
<span>{{item.name}}</span>
问题: 如何让 ng-repeat
遵守来自子指令的 html 绑定语法?还是有另一种方法可以实现这一目标?
您在其他指令中嵌入的 displayItemTemplate
指令已经插入了数据 {{name}}
和 {{item.name}}
.
如果您在 $scope 中没有这些变量,它将在您的范围内嵌入空字符串。
然后在您的 compactSelect
指令中,被嵌入的 div 的内容将被覆盖。
如果您将 displayItemTemplate
指令移动到另一个指令的模板中,重复将起作用。 (您需要删除 ng(transclude 和 transclude: true
此外,如果您使用 bindToController
,请不要将属性放在范围内。
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() {
this.name = "a name";
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>
如果我没记错的话,那么您正在尝试创建一个 list view
,这样列表的 template
将由用户提供,但是方法(点击等)将已经通过指令提供。
现在,由于 angular 1.3
,transcluded scope
是 directive isolated scope
、
因此,在您的情况下,如果您遵循正确的层次结构,则可以从用户提供的模板中访问 directive scope
。
这是您的范围层次结构:
Directive isolated scope
--> ng-repeat new scope for every row
--> transcluded scope
.
所以,如果您想从 transcluded scope
访问 directive scope
,
您需要执行 $parent
(对于 ng-repeat)然后访问 item.name
,如下所示:
<display-item-template>
<span>Item Name: {{$parent.item.name}}</span>
</display-item-template>
此外,您不需要 compact-select-tpl
中的绑定,因为您希望该内容来自嵌入:
<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>