Trying to render the window size on window resize through a stream in an angular 2 component utilizing an async
pipe:
<h2>Size: {{size$ | async | json}}</h2>
const windowSize$ = new BehaviorSubject(getWindowSize());
Observable.fromEvent(window, 'resize')
.map(getWindowSize)
.subscribe(windowSize$);
function getWindowSize() {
return {
height: window.innerHeight,
width: window.innerWidth
};
}
@Component({
selector: 'my-app',
providers: [],
template: `
<div>
<h2>Size: {{size$ | async | json}}</h2>
</div>
`,
directives: []
})
export class App {
size$ = windowSize$.do(o => console.log('size:', o));
constructor() { }
}
But the component only renders the initial state and ignores the stream updates. If you open the console, on window resize, you'll see the updates from that same stream.
Can't understand what i am missing here.
Here's a plunker
Since my goal was to be able to abstract the window size streams in a different module, apparently just wrapping the streams in a class sealed the deal:
"This is the future" version:
import {Observable, BehaviorSubject} from 'rxjs';
export class WindowSize {
width$: Observable<number>;
height$: Observable<number>;
constructor() {
let windowSize$ = createWindowSize$();
this.width$ = (windowSize$.pluck('width') as Observable<number>).distinctUntilChanged();
this.height$ = (windowSize$.pluck('height') as Observable<number>).distinctUntilChanged();
}
}
const createWindowSize$ = () =>
Observable.fromEvent(window, 'resize')
.map(getWindowSize)
.startWith(getWindowSize())
.publishReplay(1)
.refCount();
const getWindowSize = () => {
return {
height: window.innerHeight,
width: window.innerWidth
}
};
"Granny" version:
import {Observable, BehaviorSubject} from 'rxjs';
export class WindowSize {
width$: Observable<number>;
height$: Observable<number>;
constructor() {
let windowSize$ = new BehaviorSubject(getWindowSize());
this.width$ = (windowSize$.pluck('width') as Observable<number>).distinctUntilChanged();
this.height$ = (windowSize$.pluck('height') as Observable<number>).distinctUntilChanged();
Observable.fromEvent(window, 'resize')
.map(getWindowSize)
.subscribe(windowSize$);
}
}
function getWindowSize() {
return {
height: window.innerHeight,
width: window.innerWidth
};
}
Although I didn't want class/service in this module, just clear/platform-independent constructs, this was the only clean way that worked for angular without needing to care about triggering zone updates.