【问题标题】:Binding select element to object in Angular将选择元素绑定到Angular中的对象
【发布时间】:2016-06-26 23:31:53
【问题描述】:

我想将一个选择元素绑定到一个对象列表——这很简单:

@Component({
   selector: 'myApp',
   template: 
      `<h1>My Application</h1>
       <select [(ngModel)]="selectedValue">
          <option *ngFor="#c of countries" value="c.id">{{c.name}}</option>
       </select>`
    })
export class AppComponent{
   countries = [
      {id: 1, name: "United States"},
      {id: 2, name: "Australia"}
      {id: 3, name: "Canada"},
      {id: 4, name: "Brazil"},
      {id: 5, name: "England"}
   ];
   selectedValue = null;
}

在这种情况下,selectedValue 似乎是一个数字——所选项目的 ID。

但是,我实际上想绑定到 country 对象本身,以便 selectedValue 成为对象而不仅仅是 id。我尝试像这样更改选项的值:

<option *ngFor="#c of countries" value="c">{{c.name}}</option>

但这似乎不起作用。它似乎在我的selectedValue 中放置了一个对象——但不是我期望的对象。你可以see this in my Plunker example

我还尝试绑定到更改事件,以便我可以根据选定的 id 自己设置对象;但是,似乎 change 事件在绑定的 ngModel 更新之前触发——这意味着我当时无权访问新选择的值。

有没有一种干净的方法可以使用 Angular 2 将选择元素绑定到对象?

【问题讨论】:

  • 刚刚意识到我的 Plunk 在 IE 和 Chrome 中的工作方式略有不同。两者都没有真正按照我想要的方式工作,但仅供参考。

标签: html angular


【解决方案1】:
<h1>My Application</h1>
<select [(ngModel)]="selectedValue">
  <option *ngFor="let c of countries" [ngValue]="c">{{c.name}}</option>
</select>

StackBlitz example

注意:您可以使用[ngValue]="c" 代替[ngValue]="c.id",其中c 是完整的国家对象。

[value]="..." 只支持字符串值
[ngValue]="..." 支持任意类型

更新

如果value 是一个对象,则预选实例需要与其中一个值相同。

另见最近添加的自定义比较https://github.com/angular/angular/issues/13268 自 4.0.0-beta.7 起可用

<select [compareWith]="compareFn" ...

如果您想在compareFn 中访问this,请注意。

compareFn = this._compareFn.bind(this);

// or 
// compareFn = (a, b) => this._compareFn(a, b);

_compareFn(a, b) {
   // Handle compare logic (eg check if unique ids are the same)
   return a.id === b.id;
}

【讨论】:

  • 所有读者都必须仔细检查他们使用的是ngValue,而不仅仅是value,即使选择显示的文本正确。
  • 试过了,但这似乎只是从下拉到模型的数据绑定。如果进入已设置模型的页面,则未相应设置下拉菜单...
  • @Strinder 一个常见的错误是为selectedValue 使用另一个对象实例而不是c(默认项)。即使具有相同的属性和值的不同对象也不起作用,它必须是相同的对象实例。
  • @GünterZöchbauer 是的。已经想好了。那么没有简单的方法可以直接与模型和值列表同步吗? = 总是通过 onChange?
  • [ngValue] 而不是 [value] 是我的关键。谢谢。
【解决方案2】:

这可能会有所帮助:

<select [(ngModel)]="selectedValue">
  <option *ngFor="#c of countries" [value]="c.id">{{c.name}}</option>
</select>

【讨论】:

  • 我使用了 [value] 而不是 [ngValue]。这是不一样的。这对我有用
  • 角度 4 中的“#”错误
  • 使用let 而不是# @sea-kg
  • 这个答案没有得到选中的值
【解决方案3】:

您可以使用函数选择 ID

<option *ngFor="#c of countries" (change)="onchange(c.id)">{{c.name}}</option>

【讨论】:

  • (change) 函数不会为此标签触发任何事件,但适用于
  • 在这种情况下,我们不需要在这里触发任何事件,他需要捕获循环列表的 Id,以防您需要将 (Change) 事件添加到选择元素的事件如下 (Change)="myFunction($event)"
  • 你可以在 event.target.value 中找到你的 Value
  • 你还需要在 Options 元素中添加任何你想要的对象,如下所示
  • 它没有用。在选项标记上,但当我在 中使用它时开始工作
【解决方案4】:

您也可以这样做,而无需在 &lt;select&gt; 标签中使用 [(ngModel)]

在你的 ts 文件中声明一个变量

toStr = JSON.stringify;

在你的模板中这样做

 <option *ngFor="let v of values;" [value]="toStr(v)">
      {{v}}
 </option>

然后使用

let value=JSON.parse(event.target.value)

将字符串解析回一个有效的 JavaScript 对象

【讨论】:

  • 这确实是可行的,但在大型物体上会变得很痛苦。此外,Angular 的变化检测能力也是值得考虑的。以 json 格式输出信息,机器人可以轻松解析,从而提高性能。使用 Angular 的变更检测隐藏(封装)数据的逻辑,并确保您获得所需的信息。 @Günter Zöchbauer 的答案是在 Angular 中做到这一点。 :)
  • 帮助我在哪里有一个列表,并且更改一个值不应该更新下一个值,因此它有助于在不使用 ngmodel 的情况下将其用作 hack,谢谢 :)
  • 这适用于纯 JavaScript 对象,但请注意,对于类的实例,您将丢失其上的所有方法。
【解决方案5】:

你也可以在 click() 的帮助下通过函数传递选定的值来获取选定的值

<md-select placeholder="Select Categorie"  
    name="Select Categorie" >
  <md-option *ngFor="let list of categ" [value]="list.value" (click)="sub_cat(list.category_id)" >
    {{ list.category }}
  </md-option>
</md-select>

【讨论】:

    【解决方案6】:

    对我来说,它是这样工作的,你可以控制台event.target.value

    <select (change) = "ChangeValue($event)" (ngModel)="opt">   
        <option *ngFor=" let opt of titleArr" [value]="opt"></option>
    </select>
    

    【讨论】:

      【解决方案7】:

      此外,如果给定解决方案中的其他任何方法都不起作用,请检查您是否在“AppModule”中导入了“FormsModule”,这对我来说很关键。

      【讨论】:

        【解决方案8】:

        它对我有用:

        模板 HTML:

        我将(ngModelChange)="selectChange($event)" 添加到我的select

        <div>
          <label for="myListOptions">My List Options</label>
          <select (ngModelChange)="selectChange($event)" [(ngModel)]=model.myListOptions.id >
            <option *ngFor="let oneOption of listOptions" [ngValue]="oneOption.id">{{oneOption.name}}</option>
          </select>
        </div>
        

        在 component.ts 上:

          listOptions = [
            { id: 0, name: "Perfect" },
            { id: 1, name: "Low" },
            { id: 2, name: "Minor" },
            { id: 3, name: "High" },
          ];
        

        你需要添加到component.ts这个函数:

          selectChange( $event) {
            //In my case $event come with a id value
            this.model.myListOptions = this.listOptions[$event];
          }
        

        注意: 我尝试使用 [select]="oneOption.id==model.myListOptions.id" 并不起作用。

        ============= 另一种方法可以是:=========

        模板 HTML:

        我将[compareWith]="compareByOptionId 添加到我的select

        <div>
          <label for="myListOptions">My List Options</label>
          <select [(ngModel)]=model.myListOptions [compareWith]="compareByOptionId">
            <option *ngFor="let oneOption of listOptions" [ngValue]="oneOption">{{oneOption.name}}</option>
          </select>
        </div>
        

        在 component.ts 上:

          listOptions = [
            { id: 0, name: "Perfect" },
            { id: 1, name: "Low" },
            { id: 2, name: "Minor" },
            { id: 3, name: "High" },
          ];
        

        你需要添加到component.ts这个函数:

         /* Return true or false if it is the selected */
         compareByOptionId(idFist, idSecond) {
            return idFist && idSecond && idFist.id == idSecond.id;
         }
        

        【讨论】:

        • 如果您还想处理更改事件以做一些额外的事情(例如通知更改回调),这很好。虽然在这种情况下,您只需要输入[ngModel],然后在(ngModelChange) 中定义的自定义更改回调中手动设置您的模型。
        【解决方案9】:

        以防万一有人希望使用响应式表单做同样的事情:

        <form [formGroup]="form">
          <select formControlName="country">
            <option *ngFor="let country of countries" [ngValue]="country">{{country.name}}</option>
          </select>
          <p>Selected Country: {{country?.name}}</p>
        </form>
        

        检查工作示例here

        【讨论】:

        • this.form.get("country").value.Id
        【解决方案10】:

        为所选项目创建另一个 getter

        <form [formGroup]="countryForm">
          <select formControlName="country">
            <option *ngFor="let c of countries" [value]="c.id">{{c.name}}</option>
          </select>
        
          <p>Selected Country: {{selectedCountry?.name}}</p>
        </form>
        

        在 ts 中:

        get selectedCountry(){
          let countryId = this.countryForm.controls.country.value;
          let selected = this.countries.find(c=> c.id == countryId);
          return selected;
        }
        

        【讨论】:

          【解决方案11】:

          也用这种方式..

          <h1>My Application</h1>
          <select [(ngModel)]="selectedValue">
               <option *ngFor="let c of countries" value="{{c.id}}">{{c.name}}</option>
           </select>
          

          【讨论】:

            【解决方案12】:

            app.component.html:

            <select type="number" [(ngModel)]="selectedLevel">
              <option *ngFor="let level of levels" [ngValue]="level">{{level.name}}</option>
            </select>
            

            还有app.component.ts:

            import { Component } from '@angular/core';
            
            @Component({
              selector: 'my-app',
              templateUrl: './app.component.html',
              styleUrls: [ './app.component.css' ]
            })
            export class AppComponent  {
              levelNum:number;
              levels:Array<Object> = [
                  {num: 0, name: "AA"},
                  {num: 1, name: "BB"}
              ];
            
              toNumber(){
                this.levelNum = +this.levelNum;
                console.log(this.levelNum);
              }
            
              selectedLevel = this.levels[0];
            
              selectedLevelCustomCompare = {num: 1, name: "BB"}
            
              compareFn(a, b) {
                console.log(a, b, a && b && a.num == b.num);
                return a && b && a.num == b.num;
              }
            }
            

            【讨论】:

              【解决方案13】:

              关键是在select 中通过[(ngModel)] 使用双向绑定,并在每个option 中使用[ngValue]

              您甚至可以有一个默认的 null 选项,它适用于 Angular 12。

              <select name="typeFather" [(ngModel)]="selectedType">
                <option [ngValue]="null">Select a type</option>
                <option *ngFor="let type of types" [ngValue]="type">{{type.title}}</option>
              </select>
              

              这种方法总是可行的,但是如果您有一个动态列表,请确保在模型之前加载它。

              【讨论】:

                【解决方案14】:

                这段代码很简单:

                <select class="form-control" id="marasemaat" [(ngModel)]="fullNamePresentor" 
                        [formControl]="stateControl" (change)="onSelect($event.target.value)">
                  <option *ngFor="let char of programInfo1;let i = index;" 
                          onclick="currentSlide(9,false)" 
                          value={{char.id}}>{{char.title + " "}}  ----> {{char.name + " "+ char.family }} ---- > {{(char.time.split('T', 2)[1]).split(':',2)}}</option>
                </select>
                

                【讨论】:

                  【解决方案15】:

                  注意 Angular 2+ 用户: 出于某种原因, [value] 不适用于元素。请改用 [ngModel]。

                  <select [ngModel]="selectedCountry">
                      <option *ngFor="let country of countries" [value]="country">{{country.name}}</option>
                  </select>
                  

                  【讨论】:

                    【解决方案16】:

                    在 Angular 11 上测试。我需要一个额外的对象“typeSelected”。请注意,我没有像其他答案那样使用 [(ngValue)]

                    <mat-select formControlName="type" [(value)]="typeSelected" 
                                [compareWith]="typeComparation">
                      <mat-option *ngFor="let myType of allSurveysTypes" [value]="myType">
                        {{myType.title}}
                      </mat-option>
                    </mat-select>
                    
                    //Declaration.
                    typeSelected: SurveyType;
                    ...
                    
                    //Assigning variable 'type' of object 'survey' to 'typeSelected'.
                    this.typeSelected = survey?.type;
                    ...
                    
                        
                    //Function to compare SurveyType objects.
                    typeComparation = ( option, value ) =>  {
                      if (option && value) {
                        return option.id === value.id;
                      }
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2016-12-29
                      • 2020-02-17
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2012-03-23
                      • 2012-12-12
                      • 1970-01-01
                      相关资源
                      最近更新 更多