2

在我的 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 {/* ... */}
}

我的意图:

  1. 告诉my-select组件,显示的值应该userFriendlyStringFoo. 我不想硬编码,因为其他组件也应该能够my-select与其他模型类一起使用。我无法想象该怎么做。我的第一个方法是为@Input()组件设置一个回调函数my-select,但这不起作用,不应该根据这个答案来完成。第二种方法是覆盖 toString in Foo。也不起作用(我假设在any...中缺少动态调度?!)。
  2. 得到EventEmitter“预期”的工作:应该可以foo: Foo在句柄函数中有一个正确的。

那么,我还有希望吗?:)

4

2 回答 2

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);
    }
}

这样,您的所有组件都可以使用一个通用接口,并且ngValueoption元素中使用可以让您将整个对象作为值发出。

您最了解您的其他数据模型,但您可以将 map 函数放在您@Input的 select 组件中,这样每个组件就不必在将其数据发送到之前转换它的数据SelectComponent

internalSelectModel: SelectListObject[] = [];
@Input('selectModel')
set selectModel(value){
    this.internalSelectModel = value.map(x => <SelectListObject>{key: value.name, value: value};
}

handle函数对于使用 的每个组件都是唯一的SelectComponent,因此该值可以是您需要的任何类型(发送)。

希望有帮助。

于 2017-03-27T14:55:33.383 回答
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);
    }
}
于 2017-03-27T15:00:19.987 回答