Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observe resize of a dom element using rxJS

I want to add a resize observer to a div element in my dom to give me a callback when it resizes.

I know it can be done using the ResizeObserver, but as its not supported in all browsers, i would have to add a polyfill for it.

I wanted to know if i can do the same thing using rxJS? Just observing a dom element and doing something in a callback when it resizes.

like image 334
ghostCoder Avatar asked Mar 10 '19 19:03

ghostCoder


2 Answers

I would recommend use of ResizeObserver API directly and use Polyfill to handle, in case if there are no ResizeObserver in the browser [e.g. https://www.npmjs.com/package/resize-observer-polyfill].

And I think one can create a Resize DOM Observable using ResizeObserver API pretty easily, like below:

function resizeObservable(elem) {
    return new rxjs.Observable(subscriber => {
        var ro = new ResizeObserver(entries => {
            subscriber.next(entries);
        });

        // Observe one or multiple elements
        ro.observe(elem);
        return function unsubscribe() {
            ro.unobserve(elem);
        }
    });
}

Then you can call it just like normal RxJS.

resizeObservable(document.querySelector("XXXX"))
    .pipe(
        // ...
    )
    .subscribe(entries => {
        // handle as you like
    });

Using RxJS instead of ResizeObserver directly, can have several advantages, especially, when you are going to merge observables or want to use operators.

For example, when one want to create a scroll-to-bottom button, which will only appear when it is not in the bottom. Then you can easily do that by

const toggleShowBottomBtnObs$ = rxjs.merge(
    rxjs.fromEvent(document.querySelector("XXX", "scroll"),
    resizeObservable(document.querySelector("XXX"))
)
    .pipe(
        rxjs.operators.debounceTime(200),
        rxjs.operators.map(() => isBottom()),
        rxjs.operators.distinctUntilChanged(),
    )
    .subscribe(toggleShowBtn)
like image 59
CHANist Avatar answered Sep 20 '22 23:09

CHANist


Ignoring MutationObserver and animation hacks as they are not part of the question...

Perhaps in the future. But currently this limitation exists:

...resize events are only fired on (sent to) the window object (document.defaultView). Only handlers registered on the window object will receive events.

Source:https://developer.mozilla.org/en-US/docs/Web/Events/resize

Otherwise:

You are looking for the rxJS fromEvent() method for valid HTMLElement events (read: not resize).

From the docs: https://www.learnrxjs.io/operators/creation/fromevent.html

//create observable that emits click events
const source = fromEvent(document.querySelector('#myDiv'), 'click');
const subscribe = source.subscribe(evt => console.log(evt));
like image 31
Randy Casburn Avatar answered Sep 19 '22 23:09

Randy Casburn