在具有双向绑定的 <select> 中默认 Angular2 <option>

Posted

技术标签:

【中文标题】在具有双向绑定的 <select> 中默认 Angular2 <option>【英文标题】:Defaulting an Angular2 <option> in a <select> with two-way binding 【发布时间】:2016-08-06 10:44:49 【问题描述】:

我想使用 html 设置一个带有默认 &lt;option&gt;&lt;select&gt;,并通过两种方式绑定到我的模型来填充 &lt;select&gt; 的其余部分。

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 属性中没有默认值,因此 &lt;select&gt; 绑定到任何内容。我的意思是,这按预期工作。

我正在尝试弄清楚如何让默认值显示在&lt;select&gt; 中,我想这样做,而不是在我的模型中硬编码 UI 值并在新实例中默认它我的模型。 Angular 2 有办法解决这个问题吗?

编辑:

结果 HTML 应如下所示:

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

【问题讨论】:

How to show placeholder (empty option) in select control in Angular 2?的可能重复 【参考方案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 来绑定选中的值,所以你必须先将绑定属性设置为默认值,即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>

【讨论】:

从 Angular 2.2.1 开始:&lt;option [ngValue]="null"&gt;&lt;/option&gt; 是可能的。 github.com/angular/angular/commit/e0ce545【参考方案2】:

实际上,您可以创建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);
        
    

【讨论】:

这是一个非常优雅的解决方案,我尝试让它工作;但是,由于 Angular 的双向绑定模式,我不认为它可以工作。你可以用这个向&lt;select&gt; 注入一个新项目,当然,但它不会选择(即使你设置了HTMLOptionElement.selected 属性。双向绑定只会进入并覆盖任何先前选择的元素,使其成为返回默认情况下未选择的任何内容(如用户所见,而不是 DOM)。 下一步是实现 ngModel 的略微修改版本,检查这个link。【参考方案3】:

在 beta 14(参见:Angula2-beta.14 Changlog)上,Angular 在选择标签中添加了对 Object 的支持:

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

除了[value],您可以使用[ngValue] 将对象绑定到选择标记中的ngModel

您可以在Plunker 上看到一个带有默认值的示例。

selected 属性不起作用,我正在尝试通过一些解决方法在我的项目中解决此问题!

希望有用。

【讨论】:

【参考方案4】:

我也遇到了同样的问题,我们可以将 ngModel 绑定到值:

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

【讨论】:

【参考方案5】:

我已经这样做了,它对我有用:

<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>

[ngValue]="products" 表示[(ngModel)]="products"

在此之前,我有&lt;option value=""&gt;-- Select product --&lt;/option&gt;,但后来它呈现为:空白选项,--选择产品--和我的产品列表。

【讨论】:

这是 Angular 4 中唯一适合我的答案。【参考方案6】:

你正朝着正确的方向靠近。需要考虑的一件事是将模型的空值与默认选项的空字符串值进行比较。 因此,如果您比较并设置默认显示文本的空值,那么它会正常工作。 我已经按照上面的设置,它对我有用!

<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>

【讨论】:

以上是关于在具有双向绑定的 <select> 中默认 Angular2 <option>的主要内容,如果未能解决你的问题,请参考以下文章

select ipnut双向数据绑定用法

VUE的双向绑定及局部组件的使用

vue中v-model 数据双向绑定

为啥双向绑定组件在 Svelte 中更新两次?

尝试将双向数据绑定到选择元素时遇到问题[重复]

vue之表单输入绑定