【发布时间】:2015-09-04 19:08:09
【问题描述】:
给定一个包含多个字段的页面部分的模型,并将填充如下数据:
{
"fields": [
{
"id": 1,
"type": "text",
"caption": "Name",
"value": "Bob"
},
{
"id": 2,
"type": "bool",
"caption": "Over 24?",
"value": 0
},
{
"id": 3,
"type": "options",
"options" : [ "M", "F"],
"caption": "Gender",
"value": "M"
}
]
}
我想要一个通用的部分组件,它不知道它可能包装的不同类型的字段,以避免部分模板中的大量条件逻辑,并通过删除添加新的字段类型视图/组件在一个独立的文件中,而不必修改一个单独的组件。
我的理想是组件的选择器足够具体,我可以通过基于绑定到模型的属性值在父组件的模板中选择一个元素来完成此操作。例如:(请原谅我在 SO 窗口中编码时出现的任何语法问题,需要注意的主要部分是 BooleanComponent.ts 上的选择器
SectionComponent.ts
@Component({
selector: 'my-app'
})
@View({
template: `
<section>
<div *ng-for="#field of fields">
<field type="{{field.type}}"></field>
</div>
</section>
`,
directives: [NgFor]
})
class SectionComponent {
fields: Array<field>;
constructor() {
this.fields = // retrieve section fields via service
}
}
FieldComponent.ts:
// Generic field component used when more specific ones don't match
@Component({
selector: 'field'
})
@View({
template: `<div>{{caption}}: {{value}}</div>`
})
class FieldComponent {
constructor() {}
}
BooleanComponent.ts:
// specific field component to use for boolean fields
@Component({
selector: 'field[type=bool]'
})
@View({
template: `<input type="checkbox" [id]="id" [checked]="value==1"></input>`
})
class BooleanComponent {
constructor() {}
}
...随着时间的推移,我会添加新组件,为其他特定字段类型甚至带有某些标题的字段等提供特殊模板和行为。
这不起作用,因为组件选择器必须是一个简单的元素名称(至少在 alpha.26 和 alpha.27 中)。我对 github 对话的研究让我相信这个限制正在放宽,但我无法确定我想做的事情是否真的会得到支持。
另外,我已经看到提到的 DynamicComponentLoader,但现在我找不到我认为在 angular.io 指南上的示例。即便如此,我也不知道如何使用它来动态加载它不知道名称或匹配条件的组件。
有没有办法使用类似于我尝试过的技术或我在 Angular 2 中不知道的其他技术来实现我将专用组件与其父级分离的目标?
2015-07-06 更新
http://plnkr.co/edit/fal9OA7ghQS1sRESutGd?p=preview
我认为最好更明确地显示我遇到的错误。我已经包含了一些示例代码,虽然只有这 3 个错误中的第一个是可见的,因为每个错误都会阻止另一个,所以你一次只能炫耀一个。我已经硬编码暂时绕过#2和#3。
- 无论我在 BooleanComponent 上的选择器是
selector: 'field[type=bool]'还是selector: '[type=bool]',我都会从 Angular 中得到一个错误堆栈,例如组件'BooleanComponent'只能有一个元素选择器,但有'[type=bool]'
-
<field [type]="field.type"></field>没有将我的 field.type 值绑定到 type 属性,但给了我这个错误(谢天谢地,现在出现在 alpha 28 中。在 alpha 26 中,我之前在,它默默地失败了)。我可以通过将类型属性添加到我的 FieldComponent 和派生的 BooleanComponent 并将其与 @Component 属性集合连接起来来消除此错误,但我不需要它用于组件中的任何内容。无法绑定到 'type',因为它不是 'field' 元素的已知属性,并且没有具有相应属性的匹配指令
- 我不得不在我的 SectionComponent View 注释的指令列表中列出 FieldComponent 和 BooleanComponent,否则它们将不会被找到和应用。我阅读了 Angular 团队的设计讨论,他们做出了这个有意识的决定来支持明确性,以减少与外部库中指令冲突的发生,但这打破了我试图实现的插入式组件的整个想法。
在这一点上,我很难理解为什么 Angular2 还要费心使用选择器。父组件已经必须知道它将拥有哪些子组件、它们将去往何处以及它们需要哪些数据。选择器目前完全是多余的,它也可以是类名匹配的约定。我没有看到我需要解耦它们的组件之间的抽象。
由于 Angular2 框架能力的这些限制,我正在制作自己的组件注册方案并通过 DynamicComponentLoader 放置它们,但我仍然很想看到找到更好方法的人的任何回应来完成这个。
【问题讨论】:
-
好问题。我遇到了同样的问题。我发现在 alpha-34 中我们会得到部分解决方案。任何选择器都可以用于组件。你可以在这里查看github.com/angular/angular/pull/3336。但是,动态选择的问题仍然是热门话题。如果可能的话,我希望看到您使用 DynamicComponentLoader 的解决方案。
-
好问题,我们正在努力避免在页面上出现大的 swtich 或 ngIf 块。
标签: angular