angular / angular/components

bug(MatTabLink): Underline (MatTabInk) is missing if combined with route reuse strategy

オープン
#28,229 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る
area: material/tabs P3
主要言語
TypeScript
スター
25k
フォーク
6.8k
平均マージ
1日 8時間
マージ済み PR(30日)
91

説明

### 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

_No response_

### Description

We have an application with multiple layer of tabs combined with custom route reuse strategy. Most of the tabs are detached and reattached until the tab is closed.

The active tab is determined from the currently active route on each navigation end event. This way if the application is loaded with a specific url, the appropriate tab is selected.

Consider the following routes:
```
- /tab1
- /tab2
- /tab2/sub1
- /tab2/sub2
```

On the `/tab2` route, another tab group is present with links to the sub routes (and of course a sub router-outlet as well).

If we load the app with the `/tabs2/sub2` route, the components of `/tab2` and `/tab2/sub2` are loaded, which also means that the tab2's ink is initialized to the second tab in the header.

Now, if we navigate to `/tab1`, these components are not destroyed, however the tab link active flags are set to false because neither `/tab2/sub1` nor `/tab2/sub2` is active after the navigation ends.

Then if we navigate back to `/tab2/sub2`, the components are not reinitialized (because of the reuse strategy). but the active flag is changed for the `/tab2/sub2` tab link (because it is now active after navigation end).

### Reproduction

StackBlitz link: https://stackblitz.com/edit/stackblitz-starters-nckgfk?file=src%2Ftab-active-tracker.directive.ts

Steps to reproduce:
1. Click on Tab 1 -> Tab 1 highlighted [OK]
2. Click on Tab 2 -> Tab 2 highlighted [OK], inner tab group loaded [OK]
3. Click on Sub-Tab 1 -> upper Sub-Tab 1 highlighted [OK], inner Sub-Tab 1 highlighted [OK]
4. Click on Sub-Tab 2 -> upper Sub-Tab 2 highlighted [OK], inner Sub-Tab 2 highlighted [OK]
5. Click on Tab 1 -> Tab 1 highlighted [OK]
6. Click on Sub-Tab 2 -> Tab 2 highlighted [OK], **inner Sub 2 is NOT highlighted [NOK]**

### Expected Behavior

After the step 6 the ink should be re-initialized even if set to the same value.

### Actual Behavior

As you can see, the active status is properly set (font is bold on the inner Sub-Tab 2 header element) but the ink is missing.

However, I think I found the root cause of the problem.

When we navigate from the `/tab2/sub2` back to `/tab1`, neither the `/tab2/sub1` nor the `/tab2/sub2` routes are active so the `selectedIndex` is set to `-1` and the ink's `hide()` is called. However, the index just set is not processed until the next `ngAfterContentChecked` call.

Now, when we navigate back to `/tab2/sub2` (which was the last active inner tab) the ink handler thinks that despite the selection index is changed (from `-1` ro `1`), the selection itself is not changed.

I think that in the `hide()` function of `MatInkBar` the `this._currentItem` should be set to `null`. Because next time when `alignToElement` is called, the `correspondingItem === currentItem` check will be true (but the index was changed from `1 -> -1 -> 1` but it was not processed due to a missing `ngAfterContentChecked` call)

https://github.com/angular/components/blob/0762d69b394343555488b5aaada9444dd1a5083a/src/material/tabs/ink-bar.ts#L40

### Environment

```
Angular CLI: 17.0.5
Node: 18.18.0
Package Manager: npm 9.8.1
OS: win32 x64

Angular: 17.0.5
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router

Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1700.5
@angular-devkit/build-angular 17.0.5
@angular-devkit/core 17.0.5
@angular-devkit/schematics 17.0.5
@angular/cdk 17.0.2
@angular/material 17.0.2
@schematics/angular 17.0.5
rxjs 7.8.1
typescript 5.2.2
zone.js 0.14.2
```

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

src/material/tabs/ink-bar.ts から始め、特に MatInkBar.hide() と alignToElement() を確認してから、リンク先の StackBlitz で route-reuse のシーケンスを再現します。/tab2/sub2 から /tab1 へ移動して戻るときの遷移を確認します。戻った後に内側の Sub-Tab 2 の ink が再び表示されれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
angular, typescript
領域
frontend
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
停滞
明瞭さ
明確に書かれている
初心者へのやさしさ
38/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。