40484

Modify data object in ActivatedRoute

Question:

I need to modify the breadcrumb value in the data object of my current route. Here is my route configuration.

{ path: "users", component: UserListComponent, children: [ { path: ":id", component: UserComponent, data: { breadcrumb: '<User name here>' }, } ], data: { breadcrumb: 'Users' } },

I am trying to do this:

this._route.data = { breadcrumb: this.user.displayName }; //_route is ActivatedRoute

but it doesn't work. Any help would be appreciated. Thanks.

Answer1:

The data property of a route is static and cannot be modified after creation (source: <a href="https://angular.io/api/router/Data" rel="nofollow">https://angular.io/api/router/Data</a>).

There are probably many other ways to accomplish your goal. The most common method would be to grab the :id param from the route (I'm assuming this is the user id) and feed it into a UserService (which you create) that then returns the user's displayName.

<h3>A more advanced option:</h3>

While it might be overkill for your particular use case, in my app I created a breadcrumb building component which extracts static breadcrumb components from the route's data properties and renders them. For example, one of my route configs looks like:

... import { OrganizationBreadcrumbComponent } from './organization-breadcrumb.component' import { OrganizationMenuComponent } from './organization-menu.component' import { ProfileBreadcrumbComponent } from './profile/profile-breadcrumb.component' import { PeopleBreadcrumbComponent } from './people/people-breadcrumb.component' const routes: Routes = [ { path: 'organization/:organizationId', data: { breadcrumb: OrganizationBreadcrumbComponent, menu: OrganizationMenuComponent, }, canActivate: [OrganizationGuard], children: [ { path: 'profile', data: { breadcrumb: ProfileBreadcrumbComponent, }, component: ProfileComponent, }, { path: 'people', data: { breadcrumb: PeopleBreadcrumbComponent, }, component: PeopleComponent, } ], }, ]; ...

In my app, I add <em>component classes</em> (i.e. ProfileBreadcrumbComponent) to the data objects in my route config. I then have a breadcrumb rendering component which subscribes to the router's data param, extracts these breadcrumb component classes, and dynamically builds the breadcrumb trail using them. Each individual breadcrumb component can do whatever it needs to do to build its own view.

For example, you could create a UserDisplayNameBreadcrumbComponent which, in ngOnInit(), grabs the current user id from the route params, looks up that user, finds their display name, and renders it.

I actually posted a question about this a while ago (before I got everything working) that explains more, if you are interested: <a href="https://stackoverflow.com/a/43715200/5490505" rel="nofollow">https://stackoverflow.com/a/43715200/5490505</a>

I use <a href="https://github.com/ngrx/platform/blob/master/docs/router-store/README.md" rel="nofollow">ngrx/router-store</a> in my app which makes subscribing to all the breadcrumbs for a given route pretty easy.

Answer2:

I assume you want to modify the data before the navigation starts. Because it is not clear from the question.

Look for NavigationStart event and set this._route.snapshot.data instead of this._route.data.

this.router.events .filter(event => event instanceof NavigationStart) .subscribe(() => { this._route.snapshot.data = { breadcrumb: this.user.displayName }; });

Answer3:

I had a similar problem and followed the advice here: <a href="https://github.com/angular/angular/issues/13860#issuecomment-271884682" rel="nofollow">https://github.com/angular/angular/issues/13860#issuecomment-271884682</a>

Basically, the idea is that you don't define the children of the router immediately, but delay that. So, in your Routes above, just set children: [] and take that data and put it in another Routes object in the UserListComponent. Then, in that component you have something like the following for your constructor:

constructor(activatedRoute: ActivatedRoute) { activatedRoute.routeConfig.children = routes; }

So, putting it all together, two files are involved and we end up with:

// user-routing.module.ts const routes = [ { path: "users", component: UserListComponent, children: [], data: { breadcrumb: 'Users' } } ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class UserRoutingModule { constructor() { } }

and

// user.component.ts const routes = [ { path: ":id", component: UserComponent, data: { breadcrumb: '<User name here>' }, } ]; @Component({ selector: 'app-user', templateUrl: './user.component.html' }) export class UserComponent { constructor(activatedRoute: ActivatedRoute) { routes[0].data.breadcrumb = 'Bob Johnson'; activatedRoute.routeConfig.children = routes; } }

This allows you to pass what appears to be dynamic, or late-bound, data to the router since you have an instantiated class with dependencies injected with which you can do any manipulation you want on the data before attaching it to the router.

Recommend

  • Excel Index / Table of Contents - Macro
  • How to extract distinct part of a string from a file in linux
  • Mediawiki API error: Unrecognized value for parameter 'prop': extracts
  • Can't get Eclipselink level 2 cache to work
  • a simple question about lib folder in Eclipse
  • Using SWIG with a build system [closed]
  • Efficient algorithm to find additions and removals from 2 collections
  • Building Qt project for C++11 standard
  • Spring integration inbound-gateway Fire an event when queue is empty
  • Doctrine/Symfony entity generator and generating entity from one table
  • Wrong labels when plotting a time series pandas dataframe with matplotlib
  • Python ImageIO Gif Set Delay Between Frames
  • Enabling DTD support in Sql Server
  • Center align outputs in ipython notebook
  • python script hangs on input method when running spark
  • how does System.Web.HttpRequest::PathInfo work?
  • How do I include a SWC in an AS2 Flash project?
  • How to generate and display a QR Code in ionic 2
  • pyodbc doesn't report sql server error
  • Not able to aggregate on nested fields in elasticsearch
  • Zurb Foundation _global.scss meta styles for js?
  • Rails Find when some params will be blank
  • Python urlparse: small issue
  • Change JButton Shape while respecting Look And Feel
  • Jenkins: How To Build multiple projects from a TFS repository?
  • Is calc() supported in html email?
  • req.body is undefined - nodejs
  • Updating server-side rendering client-side
  • Incrementing object id automatically JS constructor (static method and variable)
  • Check if a string to interpolate provides expected placeholders
  • Symfony2: How to get request parameter
  • Matplotlib draw Spline from multiple points
  • Why winpcap requires both .lib and .dll to run?
  • Akka Routing: Reply's send to router ends up as dead letters
  • Return words with double consecutive letters
  • Is there a mandatory requirement to switch app.yaml?
  • Python: how to group similar lists together in a list of lists?
  • Free memory of cv::Mat loaded using FileStorage API
  • unknown Exception android
  • Busy indicator not showing up in wpf window [duplicate]