angularangular-materialangular-lifecycle-hookszonejszoneless

Angular Material <mat-select> Dropdown Not Interactive in Zoneless Angular 18 Until Browser Resize


Body: I am encountering a peculiar issue with Angular Material's <mat-select> dropdown in my Angular 18.1.0 application. The dropdown does not appear or interact correctly on initial page load. However, once I resize the browser window, the dropdown appears and stays open, but I cannot select any options or close it. After attempting to interact with the dropdown, the entire application hangs, requiring a hard refresh to recover.

Environment

Issue Description

In my component, simple HTML <select> elements work without any issues. The problem only occurs with Angular Material components. Here's what happens:

  1. The Angular Material dropdown does not open or display on initial load.
  2. Resizing the browser window causes the dropdown to appear and stay open.
  3. Once open, I cannot select any options or close the dropdown.
  4. Clicking on the dropdown or trying other interactions causes the entire app to hang.

Code

TypeScript:

import { Component, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { EMPTY } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';
import { ProductService, StorageService } from 'src/app/core/services';
import { IProduct, IBrand, IProductType, ISizeClassification } from 'src/app/shared/models';

@Component({
  selector: 'app-edit-product',
  templateUrl: './edit-product.component.html',
  styleUrls: ['./edit-product.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class EditProductComponent implements OnInit, OnDestroy {
  productForm!: FormGroup;
  brands = signal<IBrand[]>([]);
  // Initialization and methods...
}

HTML:

<form *ngIf="productForm" [formGroup]="productForm" (ngSubmit)="onSubmit()" class="product-form">
  <!-- Form content including mat-select and other controls -->
</form>

Specific Example of Problematic Dropdown

One particular issue I am facing is with the dropdown for selecting a brand. The dropdown does not function properly on initial load but appears after resizing the window. Below is the HTML snippet for this dropdown:

<ng-container *ngIf="brands()">
  <div class="form-group">
    <mat-form-field appearance="outline">
      <mat-label>Brand</mat-label>
      <mat-select formControlName="productBrandId" (selectionChange)="onTypeSelected($event.value!)"
          placeholder="product brands">
        <mat-option *ngFor="let brand of brands()" [value]="brand.id">
          {{brand.name}}
        </mat-option>
      </mat-select>
    </mat-form-field>
  </div>
</ng-container>

This dropdown is part of a larger form that utilizes Angular reactive forms. Despite other parts of the form behaving normally, this mat-select does not open or allow interaction unless the browser window is resized.

Additional Configuration: I recently removed zone.js and switched to using ChangeDetectionStrategy.OnPush. Before these changes, my project worked well. Here’s how my main.ts is configured:

if (environment.production) {
  enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule, { ngZone: 'noop' })
  .catch(err => console.error(err));

Attempts to Resolve

I would appreciate any insights or suggestions on what might be causing this issue or how to resolve it. Thank you!


Solution

  • To enable the experimental zoneless support, use the provider function provideExperimentalZonelessChangeDetection :

    @NgModule({
      declarations: [
        ...
      ],
      imports: [
        ...
      ],
      providers: [provideExperimentalZonelessChangeDetection()], // <== this
      bootstrap: [AppComponent],
    })
    export class AppModule {}