简体   繁体   English

在angular2中选择的问题

[英]Issue of select in angular2

Please see my plunker code i have created. 请查看我创建的插件代码。 when i click toggle show button 2 times i should get selected item. 当我单击切换显示按钮两次时,我应该会选择项目。

import {Component} from '@angular/core';

@Component({
  selector: 'my-app',
  template: `<div *ngIf="show"><select [(ngModel)]="selectedDeviceObj"  name="sel3">
    <option [ngValue]="i" *ngFor="let i of deviceObjects">{{i.name}}</option>
  </select></div>
  {{selectedDeviceObj | json}}

  <br/><br/><br/>
  <button (click)="changeShow()">toggle show</button>
  `
  //directives: []
})
export class AppComponent {
  changeShow(){  
  this.deviceObjects = [{name: 1}, {name: 2}, {name: 3}];
    this.show=!this.show;
  }

  show=true;
  title = "Angular 2 RC.4 - select";
  devices = 'one two three'.split(' ');
  selectedDevice = 'two';
  deviceObjects = [{name: 1}, {name: 2}, {name: 3}];
  selectedDeviceObj = this.deviceObjects[1];
  //constructor() { console.clear(); }
  onChange(newValue) {
    console.log(newValue);
    this.selectedDevice = newValue;
    // ... do other stuff here ...
  }
  onChangeObj(newObj) {
    console.log(newObj);
    this.selectedDeviceObj = newObj;
    // ... do other stuff here ...

  }
}

With this template and changeShow() function: 使用此模板和changeShow()函数:

@Component({
  ...
  template: `<div *ngIf="show"><select [(ngModel)]="selectedDeviceObj"  name="sel3">
    <option [ngValue]="i" *ngFor="let i of deviceObjects">{{i.name}}</option>
  </select></div>
  ...
  <button (click)="changeShow()">toggle show</button>
  `
  ...
})
export class AppComponent {
  changeShow(){  
    this.deviceObjects = [{name: 1}, {name: 2}, {name: 3}]; // <---- recreating the array!
    this.show=!this.show;
  }
  ...
  deviceObjects = [{name: 1}, {name: 2}, {name: 3}]; // <--- the "old" array
  selectedDeviceObj = this.deviceObjects[1]; // <--- points to an object of the "old" array
  ...
}

Notice that when you click the button (and changeShow() method is called), you are recreating the array the <select>/<option> s point to. 注意,单击按钮(并changeShow()方法)时,将重新创建 <select>/<option>指向的数组。

Since the selectedDeviceObj property pointed to an element of the previous deviceObjects , the <select> now has no value selected. 由于selectedDeviceObj属性指向以前的deviceObjects的元素,因此<select>现在没有选择任何值。

It may seem strange, but the change detection uses strict equality, or object identity, ( === ) to compare the objects. 看起来有些奇怪,但是更改检测使用严格的相等性或对象标识( === )比较对象。 Thus the {name: 2} in the original deviceObjects is not the same {name: 2} in the new deviceObjects (they may have the same values, but they are not the exactly same object). 因此, {name: 2}在原始deviceObjects一样的{name: 2}在新deviceObjects (它们可以具有相同的值,但它们不是完全相同的对象)。

So, if you remove the this.deviceObjects = ... line on changeShow() , the <select> should keep its selection: 因此,如果删除changeShow()上的this.deviceObjects = ...行, <select>应该保留其选择:

@Component({
  ...
  template: `<div *ngIf="show"><select [(ngModel)]="selectedDeviceObj"  name="sel3">
    <option [ngValue]="i" *ngFor="let i of deviceObjects">{{i.name}}</option>
  </select></div>
  ...
  <button (click)="changeShow()">toggle show</button>
  `
  ...
})
export class AppComponent {
  changeShow(){  
    this.show=!this.show;
  }
  ...
}

See demo plunker here . 在这里查看演示插件


Update (per comments): 更新(每条评论):

If you really need to change the whole array at each click, you can then try to update the selectedDeviceObj at each click as well: 如果确实需要在每次单击时更改整个数组,则也可以尝试在每次单击时更新selectedDeviceObj

export class AppComponent {
  changeShow(){  
    this.deviceObjects = [{name: 1}, {name: 2}, {name: 3}];
    this.show=!this.show;
    this.updateSelectedDeviceObj();
  }
  updateSelectedDeviceObj() {
    // tries to find in the new array (this.deviceObjects) if there's any object equal to
    // the this.selectedDeviceObj. If so, sets it as this.selectedDeviceObj.

    // Uses JSON.stringify() to tell if they are the same. If you have a simpler way to see
    // if the objects are the same (an ID-like property, maybe), then definitely use it.
    let jsonSelectedDeviceObj = JSON.stringify(this.selectedDeviceObj);
    this.selectedDeviceObj =
      this.deviceObjects.find(deviceObject =>
                                  jsonSelectedDeviceObj === JSON.stringify(deviceObject)
                             );
  }
  ...
}

See demo plunker here . 在这里查看演示插件

The updateSelectedDeviceObj() function above compares the objects by their JSON string. 上面的updateSelectedDeviceObj()函数通过JSON字符串比较对象。 Array.prototype.find() returns the first object in the array that satisfy the criteria (which is "JSON equality"). Array.prototype.find()返回数组中满足条件(即“ JSON相等”)的第一个对象。

Notice why this works: {name: 2} === {name: 2} is false (they are not the same object, but JSON.stringify({name: 2}) === JSON.stringify({name: 2}) is true (their JSON equivalent string is the same). 请注意为什么这样做: {name: 2} === {name: 2}false (它们不是同一对象,但是JSON.stringify({name: 2}) === JSON.stringify({name: 2})true (它们的JSON等效字符串相同)。

If you have another way to tell if the objects are the same (an ID-like property, maybe), then definitely use it. 如果您有另一种判断对象是否相同的方法(可能是类似ID的属性),则一定要使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM