Подтвердить что ты не робот

По умолчанию Angular2 <option> в <select> с двусторонней привязкой

Я хотел бы установить <select> по умолчанию <option> с помощью HTML и заполнить остальную часть <select> двумя способами привязки к моей модели.

HTML:

<select class="form-control" required
        [(ngModel)]="model.product"
        ngControl="product">
    <option value="">Select a product</option>
    <option *ngFor="#product of products" [value]="product">{{product}}</option>
</select>

Модель:

products: string[] = [
    'Foo',
    'Bar'
];

Что происходит сейчас, мой выбор является привязкой к модели, которая:

model: Entry = new Entry();

Итак, в свойстве product нет значения по умолчанию, поэтому <select> ничего не связывает. Я имею в виду, что это работает так, как ожидалось.

Я пытаюсь выяснить, как получить значение по умолчанию для отображения в <select>, хотя, и я бы хотел сделать это без жесткого кодирования значения пользовательского интерфейса в моей модели и по умолчанию, что в новом экземпляре моей модели. Имеет ли Angular 2 способ справиться с этим?

Edit:

Результат HTML должен выглядеть так:

<select>
  <option value>Select a product</option>
  <option value="foo">Foo</option>
  <option value="bar">Bar</option>
</select>
4b9b3361

Ответ 1

Я не думаю, что у Angular есть способ справиться с этим. Вам нужно будет выполнить некоторую работу:

<select class="form-control" required [(ngModel)]="model.product">
  <option *ngFor="#product of [defaultStr].concat(products)" 
   [value]="product === defaultStr ? null : product">
     {{product}}
  </option>
</select>
 
defaultStr = 'Select a product';
model = { product: null };
products: string[] = [
  'Foo',
  'Bar'
];

Plunker

Поскольку вы используете NgModel для привязки выбранного значения, вы должны сначала установить свойство bound на значение по умолчанию, которое равно null, иначе опция не будет выбрана по умолчанию:

model = { product: null };

С null я заметил, что HTML

<option value="null">Select a product</option>

Итак, вы можете предпочесть использовать пустую строку '' вместо null:

[value]="product === defaultStr ? '' : product"
model = { product: '' };

Тогда HTML

<option value="">Select a product</option>

Ответ 2

Я сделал это так и работает для меня:

<select name="Products" #Products="ngModel" [(ngModel)]="products">
  <option [ngValue]="products">-- Select product --</option>
  <option *ngFor="let p of productsList" [ngValue]="p">{{p.name}}</option>
</select>

Ответ 3

Фактически вы можете создать Directive, чтобы добавить параметр по умолчанию и обработать двустороннюю привязку:

import {Directive, ElementRef, Input, OnInit, Output, EventEmitter, HostListener} from 'angular2/core';

/**
 * <select [ngSelect]="'select number...'" [(ngSelectModel)]="model" >
 *    <option *ngFor="#item of ['1', '2', '3']" [value]="item">{{item}}</option>
 * </select>
 */
@Directive({
    selector: '[ngSelect]'
})
export class DefaultOption implements OnInit
{
    private _el:HTMLSelectElement;

    @Input('ngSelect')
    private defaultText:string;

    @Output()
    private ngSelectModelChange:EventEmitter = new EventEmitter();

    private _ngSelectModel:any;

    constructor(el:ElementRef)
    {
        this._el = el.nativeElement;
    }

    @Input()
    public get ngSelectModel():any
    {
        return this._ngSelectModel;
    }

    public set ngSelectModel(value:any)
    {
        this._ngSelectModel = value;
        if (this.ngSelectModel !== undefined)
        {
            this._el.value = this.ngSelectModel;
        }
        else
        {
            this._el.value = '';
        }
    }

    protected ngOnInit():any
    {
        var element:HTMLOptionElement = document.createElement('option');
        element.text = this.defaultText;
        element.value = '';
        this._el.insertBefore(element, this._el.firstChild);

        //delayed execution
        setTimeout(()=>
        {
            if (this.ngSelectModel !== undefined)
            {
                this._el.value = this.ngSelectModel;
            }
            else
            {
                this._el.value = '';
            }
        }, 0);
    }

    @HostListener('change', ['$event.target.value'])
    private onInput(value):void
    {
        if(value !== '')
        {
            this.ngSelectModelChange.emit(value);
        }
        else
        {
            this.ngSelectModelChange.emit(undefined);
        }
    }
}

Ответ 4

В бета-версии 14 (см.: Angula2-beta.14 Changlog), angular добавляет поддержку объекта в теги select:

<select class="form-control" required [(ngModel)]="model.product">
  <option *ngFor="#prod of products" 
   [ngValue]="prod">
     {{prod.name}}
  </option>
</select>

вместо [value], вы можете использовать [ngValue] для привязки объекта к ngModel в теге select.

Вы можете увидеть пример Plunker со значением по умолчанию.

Атрибут selected не работает, я пытаюсь исправить это в своем проекте с помощью некоторого обходного пути!

Надеюсь, что это может быть полезно.

Ответ 5

У меня точно такая же проблема, мы можем просто привязать ngModel к значению:

<option *ngFor="#product of products" [value]="model.product">{{product}}</option>

Ответ 6

Вы приближаетесь в правильном направлении. Одна вещь, которая должна учитывать, это то, что значение null модели сравнивается с пустым значением строки по умолчанию. Поэтому, если вы сравниваете и устанавливаете нулевое значение отображаемого текста по умолчанию, тогда он будет работать нормально. Я поставил выше, и он работает для меня!

<select class="form-control" 
        required
        [(ngModel)]="model.product"
        ngControl="product">
    <option value="model.product === null ? null : ''">
            Select a product
    </option>
    <option *ngFor="#product of products" 
            [value]="product">{{product}}</option>
</select>