问题
I have data set for my <select>
loaded asynchronously. I use hot observable, as the data can change in time. The problem is I am unable to set selected value and also Angular does not point to first element by itself (there is no value set until user does it). I'm trying to subscribe to my own observable and... it doesn't work, I wonder why? How can I solve this problem?
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();
}
}
}
回答1:
You subscribe to your observable twice. Async pipe does it internally after your subscription.
When subscribe
method is being executed it executes subscribe
function
observer => this.observer = observer
and overrides this.observer
property so it will have effect only for async pipe(last subscriber)
I would use share
operator to solve it
new Observable(observer => this.observer = observer).share();
Plunker Example
To see why this.observer
is overrided just run this code
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
As i mentioned early async pipe subscribes to observable internally
https://github.com/angular/angular/blob/4.3.x/packages/common/src/pipes/async_pipe.ts#L23
回答2:
You should be using
[ngValue]="value"
instead of [value]
Assigned a value as
public selectedValue: string = 'test';
HTML should be changed as
<select [(ngModel)]="selectedValue">
<option *ngFor="let value of values$ | async"
[ngValue]="value">{{ value }}
</option>
</select>
Updated Plunker
回答3:
You should bind it to ngValue:
<div>
<h2>Hello {{name}}</h2>
</div>
<select [(ngModel)]="selectedValue">
<option *ngFor="let value of (values$ | async)"
[ngValue]="selectedValue">{{ value }}
</option>
</select>
来源:https://stackoverflow.com/questions/45122300/angular-set-selected-value-for-select