javascript - Angular: sett valgt verdi for <select>


Jeg har datasett for min <select> som lastes asynkront. Jeg bruker hot observable, da dataene kan endre seg over tid. Problemet er at jeg ikke klarer å sette valgt verdi, og Angular peker heller ikke på det første elementet selv (det er ingen verdi satt før brukeren gjør det). Jeg prøver å abonnere på min egen observable og... det fungerer ikke, jeg lurer på hvorfor? Hvordan kan jeg løse dette problemet?

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();
    }
  }
}

Svar #1

Du abonnerer på observablen din to ganger. Async-pipe gjør det internt etter abonnementet ditt.

Når subscribe-metoden blir utført, kjører den subscribe-funksjonen

observer => this.observer = observer

og overstyrer this.observer-egenskapen slik at den kun vil ha effekt for async pipe (siste abonnent)

Jeg ville brukt share-operatoren for å løse det

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

Plunker-eksempel

For å se hvorfor this.observer er overstyrt, kjør bare denne koden

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

Som jeg nevnte tidligere, abonnerer async-pipen på observable internt

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

Svar #2

Du bør bruke

[ngValue]="value" 

i stedet for [value]

Tildelt en verdi som

public selectedValue: string = 'test';

HTML bør endres som

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

Oppdatert Plunker

Relaterte artikler