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();
}
}
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With