javascriptangularangular-materialmat-autocomplete

Mat-autocomplete panel should be the same width as host input, or wider depending on content


I have an angular autocomplete-tree component and I have an issue with the autocomplete panel width.

I have two requirements that I can solve individually but not together:

From Change the mat-autocomplete width?) I saw I can use [panelWidth] = "auto".

I know I can use the css styling .mat-autocomplete-panel{min-width: "300px"} but don't know how to get the width of the specific input.

So I resorted to javascript. I saw in the documentation that AutocompletePanel exposes the panel ElementRef, but this value seems to be undefined no matter what I do? Is the right way to acquire this value with @ViewChild? I have the following code that runs on the opened event.

<mat-autocomplete #autocomplete (opened)="opened()" [panelWidth]="auto" #auto="matAutocomplete">
@ViewChild("auto") autocomplete: MatAutocomplete;
@ViewChild("autoTreeInput") autoTreeInput: ElementRef;

  opened = () => {
    setTimeout(()=>{

    let p = this.autocomplete.panel?.nativeElement; //always null because panel is undefi
    console.log("opened", p, this.autocomplete);
    if (!p ) return
    p.style.minWidth =
      this.autoTreeInput.nativeElement.getBoundingClientRect().width + "px";
    },1000)
  };

Stackblitz


Solution

  • The panel elementRef shows up after (not on) opened event is fired. More specifically, after the panel is added to the DOM. So simply adding a setTimeout in which I get the element works. Unfortunately this means that the element shows up with the wrong width and then jumps to the width of the input.

    There might be a better solution, but this is what I'm going with now.

     opened = ()=> {
        let inputWidth = this.autoInput.nativeElement.getBoundingClientRect().width
        setTimeout(()=>{
          let panel = this.autocomplete.panel?.nativeElement;
    
          if (!panel ) return
          panel.style.minWidth = inputWidth + "px";
        })
      }
    

    Working stackblitz