Skip to content

ActivatedRoute.title observable does not emit changes #51401

@AleksandrSibiakov

Description

@AleksandrSibiakov

Which @angular/* package(s) are the source of the bug?

router

Is this a regression?

No

Description

The problem is that having RouteConfig.title configured as ResolveFn does not emit updates in the component via ActivatedRoute.title (which is of Observable type).
The correct/updated title value though is available in ActivatedRoute.snapshot.title.

I.e.
A route like

{
  path: ':id',
  component: SomeComponent,
  title: (snapshot) => snapshot.paramMap.get('id'),
}

and a component

export class SomeComponent implements OnInit {
 constructor(readonly route: ActivatedRoute) {
    route.params.pipe(map(() => route.snapshot.title)).subscribe(console.log); // logs every time params is updated
    route.title.subscribe(console.log); // only initial value is logged
}

I would expect both observable should log same values simultaneously, i.e. title Observable should be in sync with current snapshot.

Please provide a link to a minimal reproduction of the bug

https://stackblitz.com/edit/stackblitz-starters-v2ndqs

Please provide the exception or error you saw

No response

Please provide the environment you discovered this bug in (run ng version)

Angular CLI: 15.2.9
Node: 18.15.0
Package Manager: npm 9.5.0
OS: win32 x64

Angular: 15.2.9
... animations, cdk, cli, common, compiler, compiler-cli, core
... forms, language-service, platform-browser
... platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1502.9
@angular-devkit/build-angular   15.2.9
@angular-devkit/core            15.2.9
@angular-devkit/schematics      15.2.9
@schematics/angular             15.2.9
rxjs                            7.8.1
typescript                      4.9.5

Anything else?

I believe the cause of the issue is next:

if (!shallowEqual(currentSnapshot.data, nextSnapshot.data)) {
route.dataSubject.next(nextSnapshot.data);
}

AFAIK the title is resolved as part of route's data and stored there under symbol Symbol(RouteTitle).
ActivatedRoute.title set as projection from ActivatedRoute.data[Symbol(RouteTitle)]

So in order for ActivatedRoute.title to emit a new value the ActivatedRoute.data should emit a new value. But, as we can see above, the ActivatedRoute.data only updated when shallowEqual(currentSnapshot.data, nextSnapshot.data) == false. The thing is that symbols are not enumerated as keys of data object thus not checked for equality.

The very naive solution might be to update check as following:

 if (!shallowEqual(currentSnapshot.data, nextSnapshot.data) || currentSnapshot.title !== nextSnapshot.title) {
      route.dataSubject.next(nextSnapshot.data);
 }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions