自定义选择组件的Angular2变换模型
Posted
技术标签:
【中文标题】自定义选择组件的Angular2变换模型【英文标题】:Angular2 transform model for custom select Component 【发布时间】:2017-08-20 08:05:02 【问题描述】:在我的 angular2 应用程序中,我希望有一个可重用的选择组件,在初稿中,它看起来像这样:
import Component, Input, Output, EventEmitter from "@angular/core";
@Component(
selector: 'my-select',
template: `
<select [(ngModel)]="selectedValue" (ngModelChange)="selectionChanged()">
<option disabled="disabled" selected="selected" name="choose" value="choose">choose ...</option>
<option *ngFor="let opt of selectModel" [ngValue]="opt">
opt
</option>
</select>
`
)
export class SelectComponent
@Output()
changed: EventEmitter<any> = new EventEmitter();
@Input()
selectModel: any[] = [];
selectedValue: any = 'choose';
selectionChanged()
this.changed.emit(this.selectedValue);
不幸的是,这仅适用于字符串数组作为输入参数,因为
opt
只会为其他类型打印出[Object object]
。因此,EventEmitter 只会发出字符串。
现在,我想要的是一个组件,我可以像这样使用它:
import Component from "@angular/core";
export class Foo
bar: string;
id: number;
userFriendlyString: string = `id=$this.id|bar=$this.bar`;
constructor(bar: string, id: number)
this.bar = bar;
this.id = id;
@Component(
template: `<my-select [selectModel]="model" (changed)="handle($event)"></my-select>`
)
export class AppComponent
model: Foo[] = [new Foo('first', 1), new Foo('second', 2)];
handle(foo: Foo): void /* ... */
我的意图:
-
告诉
my-select
组件,显示的值应该是Foo
的userFriendlyString
属性。我不想硬编码,因为其他组件应该能够使用my-select
以及其他模型类。我无法想象该怎么做。我的第一个方法是为my-select
组件设置一个回调函数为@Input()
,但这不起作用,不应该这样做according to this answer。第二种方法是覆盖 Foo
中的 toString。也不起作用(我假设 any
中缺少动态调度...?!)。
让EventEmitter
工作为“预期”:应该可以在句柄函数中有一个正确的foo: Foo
。
那么,我还有希望吗? :)
【问题讨论】:
【参考方案1】:我想我要做的是创建一个通用接口,组件可以将它们的对象映射到例如:
export interface SelectListObject
key: string;
value: any;
然后将其用作选择列表组件的输入类型:
@Component(
selector: 'my-select',
template: `
<select [(ngModel)]="selectedValue" (ngModelChange)="selectionChanged()">
<option disabled="disabled" selected="selected" name="choose" value="choose">choose ...</option>
<option *ngFor="let opt of selectModel" [ngValue]="opt.value">
opt.key
</option>
</select>
`
)
export class SelectComponent
@Output()
changed: EventEmitter<any> = new EventEmitter();
@Input()
selectModel: SelectListObject[] = [];
selectedValue: any = 'choose';
selectionChanged()
this.changed.emit(this.selectedValue);
这样,您的所有组件都可以使用一个通用接口,并且在 option
元素中使用 ngValue
可以让您将整个对象作为值发出。
您最了解您的其他数据模型,但您也许可以将 map 函数放在 select 组件的 @Input
中,这样每个组件就不必在将其数据发送到 SelectComponent
之前对其进行转换:
internalSelectModel: SelectListObject[] = [];
@Input('selectModel')
set selectModel(value)
this.internalSelectModel = value.map(x => <SelectListObject>key: value.name, value: value;
handle
函数对于使用SelectComponent
的每个组件都是唯一的,因此该值可以是您需要(发送)的任何类型。
希望对您有所帮助。
【讨论】:
像魅力一样工作 :) 我也有类似的想法,但是界面的两个部分,key
和 value
是缺失的东西【参考方案2】:
你能做这样的事情吗,使用$event
,这样你就可以返回值和你想要的任何东西,并将输入设置为获取带有显示和值的对象数组:-
import Component, Input, Output, EventEmitter from "@angular/core";
interface selectModel
display: string;
value: any;
@Component(
selector: 'my-select',
template: `
<select [(ngModel)]="selectedValue" (ngModelChange)="selectionChanged($event)">
<option disabled="disabled" selected="selected" name="choose" value="choose">choose ...</option>
<option *ngFor="let opt of selectModel" [ngValue]="opt.value">
opt.display
</option>
</select>
`
)
export class SelectComponent
@Output()
changed: EventEmitter<any> = new EventEmitter();
@Input()
selectModel: selectModel[];
selectedValue: any = 'choose';
selectionChanged(event)
let response =
value: event.target.value,
foo: "something else"
this.changed.emit(response);
【讨论】:
和上面的有点像……不过我喜欢通用的输入输出接口 啊,我想我比他晚了 2 分钟才回答 :) 很高兴你解决了你的问题。以上是关于自定义选择组件的Angular2变换模型的主要内容,如果未能解决你的问题,请参考以下文章
自定义 angular2 表单输入组件,在组件内具有两种方式绑定和验证