In my Angular 2
app, I change styles based on browser window width. Here is a sample (SCSS):
.content{
/*styles for narrow screens*/
@media (max-width: 750px){
background-color:beige;
}
/*styles for medium screens*/
@media (min-width: 751px) and (max-width: 1200px) {
background-color:red;
}
/*styles for wide screens*/
@media (min-width: 1201px) {
background-color:brown;
}
}
This makes my UI responsive. I'd like my Angular components to know which width interval is current:
/* Returns which of the CSS width intervals is current*/
getWidthRange(){
let pixelWidth = ...; //what goes here?
if(pixelWidth < 251) return "small";
if(pixelWidth < 451) return "medium";
return "large";
}
A component would call this function and adjust its behavior based on width. For instance, the template below will show more content on wider screens:
<div>
{{getWidthRange()==='small'? shortText : longText}}
</div>
Even better, I would setup an Observable that emits when the browser transitions from one range to the next:
widthRangeChanges = Observable.create( observer =>
{
// ? how to detect when width changes
let oldRange = '...';
let newRange = '...';
if(newRange!==oldRange) observer.next(newRange);
}
).share(); //all subscribers share same output channel
The component could then subscribe to widthRangeChanges
and update model values when a new range is received. How can I get hold of this info in Angular 2
?
Angular 2 rc-6
, typescript 2.0.2
, rxjs 5 beta 11
You can use fromEvent
operator of RxJS:
const $resizeEvent = Observable.fromEvent(window, 'resize')
.map(() => {
return document.documentElement.clientWidth;
})
.debounceTime(200)
$resizeEvent.subscribe(data => {
this.width = data;
});
Thanks for the tip. I didn't know about
fromEvent
. Are these events proprietary to RxJS, or can I turn any JS event into an Observable this way?I guess it is only for DOM events
That's a great tip, and the Plunker as well. I will try it out. Here is a link to make the answer more helpful: reactivex.io/rxjs/class/es6/…
I used your solution. There is no need to use
map
though.fromEvent
can take a third argument, a function that returns what you want the Observable to emit. Please see plnkr.co/edit/lgkRt8nNMScPOH7QmrBS?p=previewThank you, very elegant solution!. Just one thing: In modern angular versions you should import fromEvent, map and debounceTime using this approach: stackoverflow.com/questions/50571550/…