Angular:为 <select> 设置所选值

Angular: set selected value for <select>

我的 <select> 数据集是异步加载的。我使用 hot observable,因为数据会随时间变化。问题是我无法设置选定的值,而且 Angular 本身不指向第一个元素(在用户设置之前没有设置值)。我正在尝试订阅我自己的可观察对象并且......它不起作用,我想知道为什么?我该如何解决这个问题?

PLNKR:https://plnkr.co/edit/uDmTSHq4naYGUjjhEe5Q

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
    </div>
    <select [(ngModel)]="selectedValue">
      <option *ngFor="let value of (values$ | async)"
              [value]="value">{{ value }}
      </option>
    </select>
  `,
})
export class App implements OnInit, OnDestroy {
  public name: string;
  public selectedValue: string = '';
  public values$: Observable<Array<string>> = new Observable(observer => this.observer = observer);
  protected observer: Subscriber<Array<string>>;
  protected subscription: Subscription;

  constructor() {
    this.name = `Angular! v${VERSION.full}`
  }

  ngOnInit() {
    this.subscription = this.values$.subscribe((values) => {
      console.log('never fired...');
      this.selectedValue = values[0];
    });

    setTimeout(() => {
      this.observer.next(['some', 'test', 'data']);
    });
  }

  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
}

你应该使用

[ngValue]="value" 

而不是[值]

赋值为

public selectedValue: string = 'test';

HTML 应更改为

<select [(ngModel)]="selectedValue">
  <option *ngFor="let value of values$ | async"
          [ngValue]="value">{{ value }}
  </option>
</select>

Updated Plunker

你应该将它绑定到 ngValue:

  <div>
      <h2>Hello {{name}}</h2>
    </div>
    <select [(ngModel)]="selectedValue">
      <option *ngFor="let value of (values$ | async)"
              [ngValue]="selectedValue">{{ value }}
      </option>
    </select>

您订阅了您的 observable 两次。异步管道在您订阅后在内部执行。

subscribe方法被执行时它执行subscribe函数

observer => this.observer = observer

并覆盖 this.observer 属性 所以它只对异步管道有效(最后一个订阅者)

我会用share运算符来解决

new Observable(observer => this.observer = observer).share();

Plunker Example

要了解为什么 this.observer 被覆盖,只需 运行 此代码

let myObserver;   

const observable$ = new Rx.Observable(function subscribe(observer) {
  console.log('subscribe function has been called');
  myObserver = observer;
}); 

observable$.subscribe(function next1() { console.log('next1'); });
observable$.subscribe(function next2() { console.log('next2'); });
observable$.subscribe(function next3() { console.log('next3'); });

myObserver.next();

jsbin.com

正如我提到的早期异步管道在内部订阅 observable

https://github.com/angular/angular/blob/4.3.x/packages/common/src/pipes/async_pipe.ts#L23