在我的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
组件,显示的值应该是userFriendlyString
的{{1}}属性。我不想硬编码,因为其他组件应该能够使用Foo
以及其他模型类。我无法想象如何做到这一点。我的第一个方法是为my-select
组件设置一个回调函数@Input()
,但这不起作用,不应该according to this answer。第二种方法是覆盖my-select
中的toString。不起作用(我假设在Foo
中缺少动态调度......?!)。any
工作视为'预期':应该可以在句柄函数中使用正确的EventEmitter
。那么,我有希望吗? :)
答案 0 :(得分:2)
我认为我要做的是创建一个公共接口,组件可以将对象映射到:
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);
}
}
这样,您的所有组件都可以使用通用接口,并且使用ngValue
元素中的option
可以将整个对象作为值发送。
您最了解其他数据模型,但您可以将地图功能放在选择组件的@Input
中,这样每个组件都不必转换它的数据将其发送到SelectComponent
:
internalSelectModel: SelectListObject[] = [];
@Input('selectModel')
set selectModel(value){
this.internalSelectModel = value.map(x => <SelectListObject>{key: value.name, value: value};
}
handle
函数对于使用SelectComponent
的每个组件都是唯一的,因此值可以是您需要的任何类型(发送)。
希望有所帮助。
答案 1 :(得分:0)
你可以做这样的事情,使用$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);
}
}