Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug(mat-menu): Attempting to attach an unknown Portal type #30686

Closed
1 task done
JuNe98 opened this issue Mar 21, 2025 · 8 comments
Closed
1 task done

bug(mat-menu): Attempting to attach an unknown Portal type #30686

JuNe98 opened this issue Mar 21, 2025 · 8 comments
Labels
needs: clarification The issue does not contain enough information for the team to determine if it is a real bug needs triage This issue needs to be triaged by the team

Comments

@JuNe98
Copy link

JuNe98 commented Mar 21, 2025

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

19.2.3

Description

Since @angular/material version 19.2.4 I am getting the following error when I try to open a mat-menu:

Image

It works smoothly with any Angular Material version before 19.2.4.

Reproduction

I was not able to reproduce this bug in stackblitz. I am not sure if it makes any differences but I am using NX in my repo.

EDIT: Successfully reproduced in a public repo: https://github.com/JuNe98/nx-menu-bug

My HTML template:

<button mat-button [matMenuTriggerFor]="menu" dmThemeAccent>
  <div class="language-selector-button-content">
    <img [src]="currentLanguageImage()" alt="Language" class="language-image" />
    <mat-icon>keyboard_arrow_down</mat-icon>
  </div>
</button>
<mat-menu #menu="matMenu" class="language-select-panel">
  <div class="language-menu-header">
    <span class="language-menu-label">{{ 'language' | t | cap }}</span>
  </div>
  @for (item of allLanguages(); track item.key) {
  <button
    mat-menu-item
    [class]="{ 'selected-language': item.key === currentLanguage(), 'language-slector-menu-item': true }"
    (click)="changeLanguage(item.key)"
  >
    <div class="language-selector-item-button-content">
      <div class="language-selector-item-button-content-main">
        <img [src]="item.iconFile" alt="Language" class="language-image" />
        <span>{{ item.language }}</span>
      </div>
      @if(item.key === currentLanguage()) {
      <mat-icon>check</mat-icon>
      }
    </div>
  </button>
  }
</mat-menu>

My component:

import { Component, inject, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';
import { REGISTERED_LANGUAGES, ThemeAccentDirective, TranslatePipe, TranslationService } from '@my-lib';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
import { CapitalizePipe } from '../../../pipes';

@Component({
  selector: 'idp-language-selector',
  imports: [CommonModule, MatIconModule, MatButtonModule, MatMenuModule, TranslatePipe, CapitalizePipe, ThemeAccentDirective],
  templateUrl: './language-selector.component.html',
  styleUrl: './language-selector.component.scss',
})
export class LanguageSelectorComponent {
  private readonly translationService = inject(TranslationService);
  readonly allLanguages = signal(inject(REGISTERED_LANGUAGES));
  currentLanguage = signal<string | undefined>(undefined);

  currentLanguageImage = computed(() => {
    return this.allLanguages().find((lang) => lang.key === this.currentLanguage())?.iconFile;
  });

  constructor() {
    this.currentLanguage.set(this.translationService.getCurrentLocale());
  }

  changeLanguage(language: string) {
    this.currentLanguage.set(language);
    this.translationService.changeLocale(language);
  }
}

This are my dependencies:

"dependencies": {
    "@angular/animations": "^19.2.3",
    "@angular/cdk": "19.2.6",
    "@angular/common": "^19.2.3",
    "@angular/compiler": "^19.2.3",
    "@angular/core": "^19.2.3",
    "@angular/forms": "^19.2.3",
    "@angular/material": "19.2.6",
    "@angular/material-luxon-adapter": "19.2.6",
    "@angular/platform-browser": "^19.2.3",
    "@angular/platform-browser-dynamic": "^19.2.3",
    "@angular/router": "^19.2.3",
    "@fontsource/inter": "^5.2.5",
    "@softarc/native-federation-node": "^2.0.10",
    "ag-grid-angular": "^33.1.1",
    "ag-grid-community": "^33.1.1",
    "ajv": "^8.17.1",
    "ajv-formats": "^3.0.1",
    "angular-gridster2": "^19.0.0",
    "echarts": "^5.6.0",
    "es-module-shims": "^2.0.9",
    "keycloak-angular": "^19.0.2",
    "keycloak-js": "^26.1.4",
    "luxon": "^3.5.0",
    "material-symbols": "^0.29.2",
    "monaco-editor": "^0.52.2",
    "ngx-echarts": "^19.0.0",
    "ngx-markdown": "^19.1.1",
    "ngx-monaco-editor-v2": "^19.0.2",
    "rxjs": "~7.8.0",
    "zone.js": "~0.15.0"
  },
  "devDependencies": {
    "@analogjs/platform": "^1.14.1",
    "@analogjs/vite-plugin-angular": "^1.14.1",
    "@analogjs/vitest-angular": "^1.14.1",
    "@angular-architects/native-federation": "^19.0.16",
    "@angular-devkit/build-angular": "^19.2.4",
    "@angular-devkit/core": "^19.2.4",
    "@angular-devkit/schematics": "^19.2.4",
    "@angular/cli": "^19.2.4",
    "@angular/compiler-cli": "^19.2.3",
    "@angular/language-service": "^19.2.3",
    "@eslint/js": "^9.8.0",
    "@module-federation/enhanced": "0.8.8",
    "@nx/angular": "20.6.2",
    "@nx/devkit": "20.6.2",
    "@nx/esbuild": "20.6.2",
    "@nx/eslint": "20.6.2",
    "@nx/eslint-plugin": "20.6.2",
    "@nx/jest": "20.6.2",
    "@nx/js": "20.6.2",
    "@nx/module-federation": "20.6.2",
    "@nx/playwright": "20.6.2",
    "@nx/vite": "20.6.2",
    "@nx/web": "20.6.2",
    "@nx/webpack": "20.6.2",
    "@nx/workspace": "20.6.2",
    "@openapitools/openapi-generator-cli": "^2.16.3",
    "@playwright/test": "^1.36.0",
    "@schematics/angular": "19.2.3",
    "@swc-node/register": "~1.9.1",
    "@swc/core": "~1.5.7",
    "@swc/helpers": "~0.5.11",
    "@types/jest": "^29.5.12",
    "@types/luxon": "^3.4.2",
    "@types/node": "18.16.9",
    "@typescript-eslint/utils": "^8.13.0",
    "@vitest/coverage-v8": "^3.0.9",
    "@vitest/ui": "^3.0.9",
    "angular-eslint": "^19.2.1",
    "autoprefixer": "^10.4.0",
    "esbuild": "^0.19.2",
    "eslint": "^9.8.0",
    "eslint-config-prettier": "^9.0.0",
    "eslint-plugin-playwright": "^1.6.2",
    "jest": "^29.7.0",
    "jest-environment-jsdom": "^29.7.0",
    "jest-preset-angular": "~14.5.3",
    "jsdom": "~22.1.0",
    "jsonc-eslint-parser": "^2.1.0",
    "marked": "^15.0.6",
    "ng-packagr": "19.2.0",
    "nx": "20.6.2",
    "nx-stylelint": "^18.0.0",
    "patch-package": "^8.0.0",
    "postcss": "^8.4.5",
    "postcss-url": "~10.1.3",
    "prettier": "^2.6.2",
    "stylelint": "^16.10.0",
    "stylelint-config-standard": "^36.0.1",
    "stylelint-config-standard-scss": "^14.0.0",
    "tailwindcss": "^3.0.2",
    "ts-jest": "^29.1.0",
    "ts-node": "10.9.1",
    "tslib": "^2.3.0",
    "typescript": "5.7.3",
    "typescript-eslint": "^8.26.1",
    "vite": "^6.2.2",
    "vite-tsconfig-paths": "^5.1.4",
    "vitest": "^3.0.9"
  }

Expected Behavior

Should open the MatMenu without any erros.

Actual Behavior

Nothing, only error in the console shows up.

Environment

  • Angular: 19.2.3
  • CDK/Material: =<19.2.4
  • Browser(s): Google Chrome
  • Operating System (e.g. Windows, macOS, Ubuntu): Windows 10
@JuNe98 JuNe98 added the needs triage This issue needs to be triaged by the team label Mar 21, 2025
@devversion
Copy link
Member

devversion commented Mar 21, 2025

Thanks for the report. We've tried to reproduce this a bit, but couldn't. We've recently landed some packaging changes for Material that would seem suspicious here, but after checking the fesm2022 output that we ship to npm, everything appears to be correct.

If possible, could you share more information:

Edit: I tried a fresh Analog app with mat-menu and it did work as expected as well

@devversion devversion added the needs: clarification The issue does not contain enough information for the team to determine if it is a real bug label Mar 21, 2025
@JuNe98
Copy link
Author

JuNe98 commented Mar 21, 2025

@devversion thank you for checking.

I am using @nx/angular:package if it`s that what you mean.

I get the error on npx nx run my-app:serve.

In my case I am developing microfrontends in an NX monorepo and I am facing this issue when I consume a library which holds my language-selector build with @nx/angular:package and my app is build with the native federation lib of Manfred Steyer @angular-architects/native-federation:build.

project.json of my consuming app:

{
  "name": "shell",
  "$schema": "../../node_modules/nx/schemas/project-schema.json",
  "projectType": "application",
  "prefix": "app",
  "sourceRoot": "apps/shell/src",
  "tags": [],
  "targets": {
    "build": {
      "executor": "@angular-architects/native-federation:build",
      "options": {},
      "configurations": {
        "production": {
          "target": "shell:esbuild:production"
        },
        "development": {
          "target": "shell:esbuild:development",
          "dev": true
        }
      },
      "defaultConfiguration": "production"
    },
    "serve": {
      "executor": "@angular-architects/native-federation:build",
      "options": {
        "target": "shell:serve-original:development",
        "rebuildDelay": 0,
        "dev": true,
        "port": 0
      }
    },
    "extract-i18n": {
      "executor": "@angular-devkit/build-angular:extract-i18n",
      "options": {
        "buildTarget": "shell:build"
      }
    },
    "lint": {
      "executor": "@nx/eslint:lint"
    },
    "test": {
      "executor": "@analogjs/vitest-angular:test"
    },
    "serve-static": {
      "executor": "@nx/web:file-server",
      "options": {
        "buildTarget": "shell:build",
        "port": 4200,
        "spa": true
      }
    },
    "esbuild": {
      "executor": "@angular-devkit/build-angular:application",
      "outputs": ["{options.outputPath}"],
      "options": {
        "outputPath": "dist/apps/shell",
        "index": "apps/shell/src/index.html",
        "polyfills": ["zone.js", "es-module-shims"],
        "tsConfig": "apps/shell/tsconfig.app.json",
        "inlineStyleLanguage": "scss",
        "stylePreprocessorOptions": {
          "includePaths": ["libs/public-components/src/styles"]
        },
        "assets": [
          {
            "glob": "**/*",
            "input": "apps/shell/public"
          }
        ],
        "styles": [
          "libs/public-components/src/styles/global.scss",
          "apps/shell/src/styles.scss"
        ],
        "scripts": [],
        "browser": "apps/shell/src/main.ts"
      },
      "configurations": {
        "production": {
          "budgets": [
            {
              "type": "initial",
              "maximumWarning": "500kb",
              "maximumError": "1mb"
            },
            {
              "type": "anyComponentStyle",
              "maximumWarning": "4kb",
              "maximumError": "8kb"
            }
          ],
          "outputHashing": "all"
        },
        "development": {
          "assets": [
            {
              "glob": "**/*",
              "input": "apps/shell/public",
              "output": "/"
            },
            {
              "glob": "app.config.json",
              "input": "apps/shell/dev-configs/",
              "output": "/assets/configs/"
            },
            {
              "glob": "federation.manifest.json",
              "input": "apps/shell/dev-configs/",
              "output": "/assets/"
            }
          ],
          "optimization": false,
          "extractLicenses": false,
          "sourceMap": true,
          "namedChunks": true
        }
      },
      "defaultConfiguration": "production"
    },
    "serve-original": {
      "executor": "@nx/angular:module-federation-dev-server",
      "options": {
        "port": 4200,
        "publicHost": "http://localhost:4200"
      },
      "configurations": {
        "production": {
          "buildTarget": "shell:esbuild:production"
        },
        "development": {
          "buildTarget": "shell:esbuild:development",
          "proxyConfig": "apps/shell/src/proxy.conf.json"
        }
      },
      "defaultConfiguration": "development"
    },
    "stylelint": {
      "executor": "nx-stylelint:lint",
      "outputs": ["{options.outputFile}"],
      "options": {
        "lintFilePatterns": ["apps/shell/**/*.scss"]
      }
    }
  }
}

project.json of my lib:

{
  "name": "public-components",
  "$schema": "../../node_modules/nx/schemas/project-schema.json",
  "sourceRoot": "libs/public-components/src",
  "prefix": "idp",
  "projectType": "library",
  "tags": [],
  "targets": {
    "build": {
      "executor": "@nx/angular:package",
      "outputs": ["{workspaceRoot}/dist/{projectRoot}"],
      "options": {
        "project": "libs/public-components/ng-package.json"
      },
      "configurations": {
        "production": {
          "tsConfig": "libs/public-components/tsconfig.lib.prod.json"
        },
        "development": {
          "tsConfig": "libs/public-components/tsconfig.lib.json"
        }
      },
      "defaultConfiguration": "production"
    },
    "test": {
      "executor": "@nx/vite:test",
      "outputs": ["{options.reportsDirectory}"],
      "options": {
        "reportsDirectory": "../../coverage/libs/public-components"
      }
    },
    "lint": {
      "executor": "@nx/eslint:lint"
    },
    "stylelint": {
      "executor": "nx-stylelint:lint",
      "outputs": ["{options.outputFile}"],
      "options": {
        "lintFilePatterns": ["libs/public-components/**/*.scss"]
      }
    }
  }
}

Hope this helps :)

@JuNe98
Copy link
Author

JuNe98 commented Mar 21, 2025

@devversion I also get some strange warnings since 19.2.4:

Image

Final component which holds my language selector looks like this:

Image

Here is the HTML template for this component:

<button mat-icon-button class="menu-button" #navMenuTrigger="matMenuTrigger" [matMenuTriggerFor]="navMenu" dmThemeAccent>
  <mat-icon>apps</mat-icon>
</button>
<mat-menu #navMenu="matMenu" class="idp-nav-menu">
  @for (item of allNavItemsBlock(); track $index) {
  <ng-container *ngTemplateOutlet="navitem; context: { $implicit: item }"></ng-container>
  } @if (isNavigationPinned()) {
  <button mat-menu-item (click)="unpinMenu()">
    <mat-icon>keep_off</mat-icon>
    <span class="menu-item-label">{{ 'unpin' | t | cap }}</span>
  </button>
  } @else {
  <button mat-menu-item (click)="pinMenu()">
    <mat-icon>keep</mat-icon>
    <span class="menu-item-label">{{ 'pin' | t | cap }}</span>
  </button>
  }
</mat-menu>

<div class="logo-outer-container">
  <div class="logo-container">
    <img [src]="headerNavConfig().logoUrl" alt="Logo" class="logo" />
  </div>
</div>
<div class="actions-container">
  <!-- @if(headerNavConfig().showLanguageSelector) { -->
  <idp-language-selector></idp-language-selector>
  <!-- } -->
  <div class="user-info-circle" #userMenuTrigger="matMenuTrigger" [matMenuTriggerFor]="userMenu" tabindex="0" [matTooltip]="firstLastName()">
    <span>{{ firstLetters() }}</span>
  </div>
</div>

<mat-menu #userMenu="matMenu" class="idp-nav-menu">
  <span mat-menu-item disabled>{{ firstLastName() }}</span>
  <button mat-menu-item (click)="clickLogout()">
    <mat-icon>logout</mat-icon>
    <span class="menu-item-label">{{ 'logout' | t | cap }}</span>
  </button>
</mat-menu>

<ng-template #navitem let-item>
  <button mat-menu-item [disabled]="item.disabled" [routerLink]="item.link" class="idp-nav-item" [class.active]="currentPath.indexOf(item.link) >= 0">
    <mat-icon>{{ item.icon }}</mat-icon>
    <span>{{ item.titleTranslateKey ? (item.titleTranslateKey | t | cap) : item.title }}</span>
  </button>
</ng-template>

@devversion
Copy link
Member

I will try to look into the information you shared, but as an immediate hint in case you are looking: These new warnings are a sign that somehow you end up with two versions of the Angular CDK. There are two versions bundled; and that's causing the issue.

@JuNe98
Copy link
Author

JuNe98 commented Mar 21, 2025

I will try reproduce this bug in a new repo and share it with you.

@JuNe98
Copy link
Author

JuNe98 commented Mar 21, 2025

@devversion I have successfully reproduced the bug in a new repo: https://github.com/JuNe98/nx-menu-bug

If you think it's a builder problem, please let me know and I will open a ticket at https://github.com/angular-architects/module-federation-plugin

@devversion
Copy link
Member

@JuNe98 Thanks for the reproduction. That really helps. A few things:

I'll close this here as I don't think it's something we can act upon. Feel free to cc me on the federation issue. Happy to join the conversation; and if it doesn't work out as expected, we are surely happy to work together with e.g. Manfred


Image

@JuNe98
Copy link
Author

JuNe98 commented Mar 21, 2025

@devversion thank you for your investigation and time.

I have opened up a ticket there: angular-architects/module-federation-plugin#801

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs: clarification The issue does not contain enough information for the team to determine if it is a real bug needs triage This issue needs to be triaged by the team
Projects
None yet
Development

No branches or pull requests

2 participants