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(Tabs): ExpressionChangedAfterItHasBeenCheckedError when providing MatTabNavPanel to tabPanel input of mat-tab-nav-bar #28379

Open
1 task done
muenchto opened this issue Jan 5, 2024 · 4 comments · May be fixed by #28380
Labels
area: material/tabs P4 A relatively minor issue that is not relevant to core functions

Comments

@muenchto
Copy link

muenchto commented Jan 5, 2024

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

Angular Material pre-MDC

Description

mat-tab-nav-bar requires a reference to it's MatTabNavPanel via the tabPanel input. Documentation says this is optional but code makes it required as reported in #26270.

However, when the mat-tab-nav-bar is wrapped in some other component, e.g. an AppHeaderComponent, but the MatTabNavPanel is outside this component, we need to pass the reference to the MatTabNavPanel via Input into the wrapper component like AppHeaderComponent and then use it in the template. This is the only way I can think of, but it throws a ExpressionChangedAfterItHasBeenCheckedError (quite obvious for everyone who understand Angular's CD resolution algorithm really good, but hard to understand for everyone else), for example

ERROR Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'attr.aria-labelledby': 'mat-tab-link-4'. Current value: 'mat-tab-link-2'. Expression location: TabNavBarBasicExample component.

Reproduction

StackBlitz link: https://stackblitz.com/edit/udrwuw?file=src%2Fexample%2Ftab-nav-bar-basic-example.html
Steps to reproduce:

  1. Open developer console in browser
  2. Click around on the Nav Items
  3. Observe error in developer console

Expected Behavior

No error. I suggest simply making tabPanel optional like stated in Documentation, but of course would be nice to have a good solution to use mat-tab-nav-bar in a wrapper component

Actual Behavior

ExpressionChangedAfterItHasBeenCheckedError

Environment

  • Angular: 16+
  • CDK/Material: 16+ aka MDC
  • Browser(s): any
  • Operating System (e.g. Windows, macOS, Ubuntu): any
@muenchto
Copy link
Author

muenchto commented Jan 5, 2024

Workaround is to not using any MatTabNavPanel. Instead, create some readonly mockTabPanel = new MatTabNavPanel(); in the wrapper component (e.g. AppHeaderComponent) and provide it in the template: <nav mat-tab-nav-bar [tabPanel]="mockTabPanel">.

Of course, you dont have any of the advantages of passing a real reference to the actual panel that is used to display the content selected by the mat-tab-nav-bar.

@atscott
Copy link
Contributor

atscott commented Jan 5, 2024

@muenchto The example doesn't seem to be working. Can you make sure it's showing the problem effectively? app-nav-wrapper refers to an scss file that doesn't exist and even after fixing that issue, I'm not seeing the described error when clicking around.

@muenchto
Copy link
Author

muenchto commented Jan 5, 2024

@atscott Thanks! Seems that I did not save the stackblitz before sharing it. Fixed now. Sorry for the inconvience!

atscott added a commit to atscott/components that referenced this issue Jan 5, 2024
…tab changes

Using signals eliminates the `ExpressionChangedAfterItHasBeenCheckedError` when
an active tab changes after the tab panel has been checked.

fixes angular#28379
@crisbeto crisbeto added P4 A relatively minor issue that is not relevant to core functions area: material/tabs and removed needs triage This issue needs to be triaged by the team labels Jan 8, 2024
@EliezerB123
Copy link

EliezerB123 commented Jan 14, 2024

Workaround is to not using any MatTabNavPanel. Instead, create some readonly mockTabPanel = new MatTabNavPanel(); in the wrapper component (e.g. AppHeaderComponent) and provide it in the template: <nav mat-tab-nav-bar [tabPanel]="mockTabPanel">.

Of course, you dont have any of the advantages of passing a real reference to the actual panel that is used to display the content selected by the mat-tab-nav-bar.

While this theoretically works, the ARIA accessibility is all messed up, and tabIndex on all elements is all set to -1 when using a fake tabPanel to suppress errors. (Because it thinks that none of the items are "active")

So adding a fake [tabPanel] is not really a solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: material/tabs P4 A relatively minor issue that is not relevant to core functions
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants