Resizing elements in angular with ResizeObserver

0

In Angular apps, when it comes to responding to changes in the size of an element, web developers have several choices: a) you can create a Resize Directive or b) you can use the Resize Observer API. It provides a powerful way to monitor an item for changes in its size, with notifications sent to the viewer whenever the size changes. This web development tutorial will explain how to import and use the Resize Observer in your Angular apps.

ResizeObserver Basics in Angular

One of the main attributes of responsive design is its responsiveness to changes in the size of an element. In years past, their actual implementations were often hacked and / or fragile. In addition, applications could only monitor changes made to the viewport; changes to the size of specific items – especially those that weren’t some container – weren’t available, at least not without jumping through lots of hoops. Now thanks to Resize Observer, applications can react to changes in the size of any observed item, regardless of the cause of the change. the Resize Observer also gives access to the new size of the observed elements.

Web developers can instantiate a Resize Observer like any other object, via the New keyword. Its constructor accepts a callback function that is invoked whenever the size of the observed elements changes. The callback receives an array of Resize the Observer entry objects (one entry per observed element) containing the new dimensions of each element. To start monitoring an item, we call the observe () method and pass it the element:

const resizeObserver = 
  new ResizeObserver(callbackFunction);
resizeObserver.observe(observedElement);

When we want to stop monitoring, we call the do not observe () method, passing the relevant element:

resizeObserver.unobserve(observedElement);
resizeObserver.disconnect();

Read: Ten Ways to Use Angular JS

Using ResizeObserver in Angular Applications

As with most Angular libraries, the best way to install it is via npm. the resize-watcher-polyfill the library is a good choice. It is a polyfill for the Resize Observer API based on Observer of the mutation. He uses Mutation events as a fallback if the former is not supported. the resize-watcher-polyfill also handles CSS transitions / animations and can even observe changes caused by dynamic CSS pseudo-classes like :float. Here is the install command:

npm install resize-observer-polyfill --save-dev

Use resize-watcher-polyfill in our Angular apps, just import the library as follows:

import ResizeObserver from 'resize-observer-polyfill';

here is a AppComponent who oversees the Document body and prints a message to the console each time its size changes:

import { Component, OnDestroy } from "@angular/core";
import ResizeObserver from 'resize-observer-polyfill';

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnDestroy {
  private resizeObserver: ResizeObserver;
  private readonly observedElement = document.body;

  constructor() {
    this.resizeObserver = 
      new ResizeObserver(this.resizeCallback);
    this.resizeObserver.observe(this.observedElement);
  }

  ngOnDestroy(): void {
    this.disconnectResizeObserver();
  }

  private resizeCallback() {
    console.log("callback called");
  }

  private disconnectResizeObserver() {
    this.resizeObserver.unobserve(this.observedElement);
    this.resizeObserver.disconnect();
  }
}

Note that we are disconnecting from Resize Observer in ngOnDestroy to avoid memory leaks.

Introducing Debounce to Reduce Callback Calls

If we look at the console output produced by the above code, it becomes evident that our callback function is invoked multiple times for each modification of the Document body Cut:

Depending on what we’re doing in the booster, we may want to slow down the summons a bit. This is easily done by using an anti-rebound. This is a special type of delay related to RxJS Observables where the application waits a predetermined amount of time before notifying the subscribers. RxJS is a JavaScript library widely used by Angular developers to handle asynchronous processes of all kinds. Observables are the heart of the library and are a special type of object that notifies listeners when it receives data from an asynchronous source. In RxJS, listeners are called subscribers.

In addition to different types of observables and subscribers, RxJS has an insane number of methods to manipulate the data transmitted to subscribers. Such a method is called debounceTime (). It accepts an argument for the number of milliseconds to wait before moving data through the channel. Our problem is that we don’t have an observable; what we have is an object that invokes a callback method. Although we cannot convert a ResizeObserver to an Observable, we can wrap the first with the second by extending the Observable class:

class ResizeObservable extends Observable<ResizeObserverEntry[]> {
  constructor(elem: HTMLElement) {
    super(subscriber => {
        const ro = new ResizeObserver(entries => {
            subscriber.next(entries);
        });
  
        // Observe one or multiple elements
        ro.observe(elem);
  
        return function unsubscribe() {
            ro.unobserve(elem);
            ro.disconnect();
        }
    });
  }
}

This will allow us to use the RxJS debounceTime () function to add some delay between callback calls:

public startObserver() {
  this.resizeObserverSubscription = 
    new ResizeObservable(this.observedElement)
      .pipe(debounceTime(200))
      .subscribe(this.resizeCallback);
}

private resizeCallback() {
  console.log("callback called");
}

Read: RxJS Observables in Angular Primer

Clean up subscriptions in Angular

We need to unsubscribe from ResizeObservable in ngOnDestroy so that we do not leave it active after the end of the application; otherwise, we will create a memory leak:

export class AppComponent implements OnDestroy {
  ngOnDestroy(): void {
    if(!this.resizeObserverSubscription.closed) {
      this.resizeObserverSubscription.unsubscribe();
    }
  }
}

There is a demo of the Resize Observer in action on stackblitz. You can drag the browser window to different widths to see the output in the console. After clicking on the Using ResizeObserver with Debounce button, you should see less output produced than before.

Resize elements in Angular

Conclusion on the resizing of elements in angular

In this tutorial we have used the Resize Observer API to respond to changes in the size of an HTML element in an Angular application. With or without anti-rebound, the Resize Observer can help make your Angular apps more responsive than ever.

Read: Graceful handling of RxJS errors


Source link

Share.

About Author

Comments are closed.