The issue persists wherein getBoundingClientRect fails to provide the accurate value following a resize

I have implemented a custom directive that appends a dropdown to the body when it is displayed. The logic functions correctly when executed within the ngAfterViewInit lifecycle, but I encounter issues when attempting to use the same logic within the window.resize event because the getBoundingClientRect method does not return accurate values.

@Directive({
    selector: '[appendDropdownToBody]'
})
export class AppendDropdownToBodyDirective implements AfterViewInit {
    constructor(
        private _el: ElementRef,
        private _renderer: Renderer2,
        private _changeDetectorRef: ChangeDetectorRef
    ) {}

    ngAfterViewInit() {
        //Works fine
        this.appendToBody();
    }

    @HostListener('window:resize', ['$event'])
    onResize(event: Event) {
        //Not working properly
        this.appendToBody();
    }

    private appendToBody() {
        const dropdownEl = this._el.nativeElement as HTMLElement;
        const parentEl = dropdownEl.parentElement as HTMLElement;
        const parentElRect = parentEl.getBoundingClientRect() as DOMRect;
        this._renderer.appendChild(document.body, dropdownEl);

        this._renderer.setStyle(
            dropdownEl,
            'top',
            parentElRect.bottom + 10 + 'px'
        );
        this._renderer.setStyle(dropdownEl, 'left', parentElRect.left + 'px');
        this._renderer.setStyle(dropdownEl, 'width', parentElRect.width + 'px');
    }
}

Answer №1

It's possible that the issue stems from a lag between the window's resizing and the element's resizing. This could be due to another event listener that adjusts the element size after the initial listener is triggered.

To address this, you can utilize a ResizeObserver to monitor changes in the element itself. Learn more about ResizeObserver here: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver

@Directive({
  selector: '[resizeListener]',
})
export class ResizeListenerDirective {
  observer = new ResizeObserver(this.callback);

  constructor(private el: ElementRef) {}

  ngAfterViewInit() {
    this.observer.observe(this.el.nativeElement);
  }

  callback(entries: ResizeObserverEntry[], observer: ResizeObserver) {
    console.log(entries[0].target.getBoundingClientRect());
  }

  ngOnDestroy() {
    this.observer.disconnect();
  }
}

Check out the code on Stackblitz: https://stackblitz.com/edit/angular-ivy-hjxxkk?file=src/app/resize-listener.directive.ts

Please note: You may need to include @types/resize-observer-browser to access TypeScript types.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it feasible to use a component in a recursively manner?

Following a two-hour search for a solution, I decided to reach out to experts as I suspected the answer might be simpler than expected. The project in question is an Angular7 one. In my goals component, I aim to include a "goal" with a button labeled "+". ...

Custom filtering for a RadListView with a unique search term

Can a filtering function be passed to an Angular Nativescript RadListView that can access the local variable 'searchTerm'? The provided sample seems to suggest using a static search term, but I want to modify it based on user input. Different Ap ...

"Connecting multiple URLs to the same router link: A step-by-step guide

I am currently working on a small test project in Angular and I aim to incorporate a side navigation using Angular router outlet. My goal is to have two links: <a class="nav-link text-white" [routerLink]='["/link/to/one"]' routerLinkActive="a ...

The comparison between ng-content and router-outlet in Angular 2

Can someone help me decide on the best approach for structuring my components? i. The first approach involves using ng-content in the parent component and then creating child components enclosed within the parent's selector. For example, creating a ...

How to assign a custom validator parameter to a form group in Angular

I'm in a situation where I have a form group and need to validate the end date so it is not earlier than the start date. The challenge here lies in accessing specific fields when the form group is not yet declared. dateFormGroup: this.fb.group({ ...

Encountering a 400 bad request error while trying to retrieve an authentication token from an API url in Angular

I encountered a problem in my Angular 6 application where I am receiving an Http 400 Bad Request error when attempting to call the API url for login token. The interesting thing is that the API works perfectly fine when accessed through POSTMAN. However, ...

Transmit information from an IONIC 3 application to a PHP server using the POST method

Having trouble sending data from Ionic 3 to php via the http library using post? When php tries to retrieve it, it's unable to locate. Below is the Typescript file that generates the token to be sent to php and calls the php file on localhost (xampp) ...

Bring in Lambda layers on your local device

I've been trying to create a lambda function with a layer, but I'm stuck on how to get it running locally. Here's the current directory structure: - projectDir/ | - lambdas/ | | - match-puller/ | | | - scr/... | | | - index.ts | | ...

Unlock the Power of Angular with Custom Decorators: Accessing ElementRef Made Easy

I am currently working on implementing a decorator for Host CSS Variable Binding in Angular5. However, I am facing difficulties in properly implementing it with the given code. Is there a way to define ElementRef from within the decorator itself? export f ...

Using React to make an API call without utilizing hooks

Hello, I am currently working on developing a webpart using SharePoint and React. However, I am facing some issues with fetching data from a simple API. export default class Testing100 extends React.Component<ITesting100Props, {}> { constructor(p ...

What is the best way to associate dates with a particular ID within a textfield's value?

I am working with an array of objects called dates, and each object in the array looks like this: {id: 9898, date: 10/06/2020}. Within this array, there are multiple objects with the same id, and I want to display dates with the same id in a TextField com ...

Yes, it's not able to retrieve the value from headlessui combobox

I have encountered an issue while using the Headlessui combobox component in conjunction with Yup. Despite successfully storing the selected value in the selectedMemory state variable, Yup consistently generates a required error message. I seem to be overl ...

BehaviorSubject does not retain duplicate entries in the array

When adding values to a service and component, the first value in the array changes to the second value. Here is an overview of the code: Service export class PrepayService { private _carts: BehaviorSubject<ShoppingCart[]>; carts : Observable ...

What is the process of creating a callback in Angular using TypeScript?

Despite finding numerous resources, I am still struggling to fully grasp the concept at hand. The issue revolves around two functions in particular: roulette_animation(){ do animation (may take 5 sec) } alertResult(){ alert('You win') } My obje ...

Creating a NgFor loop in Angular 8 to display a dropdown menu styled using Material

I'm currently facing an issue with incorporating a Materialize dropdown within a dynamically generated table using *ngFor. The dropdown does not display when placed inside the table, however, it works perfectly fine when placed outside. <p>User ...

Guide on transferring individual key values from an array to another array sequentially by clicking a button in Angular/JavaScript

I have an array of objects called marrayval. From this array, I want to extract the 'country' values one by one and push them into the arrayval after each click event. For example, on the first click, I would push C1, on the second click C1, C2, ...

Guide to transforming a TaskOption into a TaskEither with fp-ts

I have a method that can locate an item in the database and retrieve a TaskOption: find: (key: SchemaInfo) => TO.TaskOption<Schema> and another method to store it: register: (schema: Schema) => TE.TaskEither<Error, void> Within my regis ...

In TypeScript, the 'onChange' is declared multiple times, therefore this particular usage will be scrutinized carefully

Within my React project, I am utilizing material-ui, react-hook-form, and Typescript. However, I encountered an error in VSCode when attempting to add the onChange function to a TextField component: 'onChange' is specified more than once, resul ...

Cannot display value in NumericFormat when using MUI TextField due to prefix restrictions

When using MUI TextField with the NumericFormat and prefix prop, there seems to be an issue. If I start typing a number quickly, only one digit gets registered. On the other hand, if I type slowly all my numbers show up but the prefix disappears. All inp ...

Adjusting the size of the div both horizontally and vertically in Angular 5 using the mouse cursor

As a beginner in Angular 5, I am looking to achieve horizontal and vertical resizing of a div by dragging with the mouse pointer. Can someone assist me in implementing this feature? ...