将绑定传递给组件中的嵌入范围
Posted
技术标签:
【中文标题】将绑定传递给组件中的嵌入范围【英文标题】:Passing a binding to transcluded scope in component 【发布时间】:2017-01-27 05:44:07 【问题描述】:在 AngularJS 1.5 中,我想将一个组件的绑定传递到(多槽)转置范围中 - 用于模板中的引用(在一个特定的或所有的模板中 - 没有任何一种方式是好的)。
这是为了创建一个通用的自定义选择列表
// Component
.component('mySelect',
bind:
collection: '<'
,
transclude:
header: 'mySelectHeader',
item: 'mySelectItem'
,
templateUrl: 'my-select-template',
controller: function()
.....
);
...
// Component template
<script id="my-select-template" type="text/ng-template">
<ol>
<li ng-transclude="header"> </li>
<li ng-transclude="item"
ng-click="$ctrl.select($item)"
ng-repeat"$item in $ctrl.collection">
</li>
</ol>
</script>
...
// Example usage
<my-select collection="[id: 1, name: "John", id: 2, name: "Erik", ... ]>
<my-select-head></my-select-head>
<!-- Reference to $item from ng-repeate="" in component -->
<my-select-item>$item.id: $item.name</my-select-item>
</my-select>
这可能来自.component()
吗?带有transclusion
的自定义指令?
【问题讨论】:
嵌入本质上与您想要实现的目标相反。 【参考方案1】:我也遇到了这个问题,在 salih 的回答的基础上,我想出了一个解决方案(免责声明 - 见底部:我认为这不一定是解决您的问题的最佳方法)。它涉及创建一个用于 mySelect 组件的存根组件,如下所示:
.component('item',
require: mySelect: '^mySelect' ,
bind: item: '<'
)
然后,调整您的模板:
<script id="my-select-template" type="text/ng-template">
<ol>
<li ng-transclude="header"> </li>
<li ng-click="$ctrl.select($item)"
ng-repeat"$item in $ctrl.collection">
<item item="$item" ng-transclude="item"></item>
</li>
</ol>
</script>
这意味着总是有一个 item 组件具有绑定到它的值。现在,您可以在自定义组件中将其用作要求:
.component('myItemComponent',
require:
itemCtrl: '^item',
template: '<span>$ctrl.item.id: $ctrl.item.name</span>',
controller: function()
var ctrl = this;
ctrl.$onInit = function()
ctrl.item = ctrl.itemCtrl.item;
);
并使用它:
<my-select collection="[id: 1, name: "John", id: 2, name: "Erik", ... ]>
<my-select-head></my-select-head>
<my-select-item>
<my-item-component></my-item-component>
</my-select-item>
</my-select>
在我实施这个之后,我实际上决定改变我的策略;这也可能对您有用。我没有使用 transclude,而是传入了一个格式化函数,即:
.component('mySelect',
bind:
collection: '<',
customFormat: '&?'
,
transclude:
header: 'mySelectHeader'
,
templateUrl: 'my-select-template',
controller: function()
var ctrl = this;
ctrl.format = function(item)
if(ctrl.customFormat)
return customFormat(item: item);
else
//default
return item;
.....
);
然后在模板中,只需使用:
<script id="my-select-template" type="text/ng-template">
<ol>
<li ng-transclude="header"> </li>
<li ng-click="$ctrl.select($item)"
ng-repeat"$item in $ctrl.collection"
ng-bind="::$ctrl.format($item)">
</li>
</ol>
</script>
如果您有任何反馈或问题,请告诉我!
【讨论】:
【参考方案2】:在您的父组件中,my-select 保留一个变量,如“selectedItem”
在您的子组件 my-select-item 中,要求您的父组件如下所示
require:
mySelect: '^mySelect'
在你的 my-select-item 组件的控制器中,访问你的父组件
$onInit = () =>
this.mySelectedItem= this.mySelect.selectedItem; // to use it inside my-select-item component.
;
select($item)
this.mySelect.selectedItem = $item; // to change the selectedItem value stored in parent component
以便现在可以从以下位置访问所选项目
<my-select-item>selectedItem.id: selectedItem.name</my-select-item>
【讨论】:
是的!就是这样,我在想如何实现这一点!太糟糕了,我们不能将它挂钩到 $onChanges 生命周期事件中。尽管 $doCheck 可以为我们处理它,但感觉有点脏。以上是关于将绑定传递给组件中的嵌入范围的主要内容,如果未能解决你的问题,请参考以下文章