Home > Software engineering >  Angular Routes data parameter as url value
Angular Routes data parameter as url value

Time:01-07

Is it possible to add url value in Angular Router as data?

Example:

const routes: Routes = [
    {path: ':id', component: ProductComponent, data: {breadcrumb: {alias: 'ProductDetail'}}},
    {
        path: 'edit/:id',
        canActivate: [AuthGuard],
        component: ProductEditComponent,
        data: {breadcrumb: {alias: 'ProductEdit'}, id: ':id'}
    },
];

I would like to pass id parameter.

CodePudding user response:

Sure, it's overkill for this scenario, but you can implement the Resolve interface to retrieve the :id portion of the activated route.

This would normally be done when you needed to fetch the product from persistence or perform some other setup logic before rendering the edit component. Your resolver would do some work before the route was finished being matched.


First, create the resolver:

import { Injectable } from "@angular/core";
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from "@angular/router";
import { Observable } from "rxjs";

// Expects 'example.com/.../edit/:id' or 'example.com/.../edit/:id/.../'.
const ID_PATTERN = /(?:edit\/)([^\/]]*)/;

@Injectable({ providedIn: 'root' })
export class ProductIdResolver implements Resolve<string> {
  
  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<string>|Promise<string>|string {
    
    // example.com/products/1
    const url = state.url;

    // ['products', '1']
    const matches = url.match(ID_PATTERN);
    
    // '1'
    const id = matches[1];

    return id;
  }
}

Then add it to your route configuration:

/* In app.module.ts or wherever you configure your routes. */

const routes: Routes = [
  { 
    path: 'edit/:id', 
    component: ProductEditComponent, 
    resolve: {
      id: ProductIdResolver
    },
    data: { breadcrumb: { alias: 'ProductEdit' } }
  }
];

Finally, access it in your component just like you would any other item on the data object:

import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-product-edit',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css']
})
export class ProductEditComponent {

  id: string | undefined;

  constructor(private activatedRoute: ActivatedRoute) {
    this.activatedRoute.data.subscribe(({ id, breadcrumb }) => {
      this.id = id;
    });

    // Or, if you know your resolved value is available immediately:
    // this.id = this.activatedRoute.snapshot.data['id'];
  }
}

For a simple case like this, you could even use an inline function that matches the ResolveFn signature.

/* In app.module.ts or wherever you configure your routes. */

// Expects 'example.com/.../edit/:id' or 'example.com/.../edit/:id/.../'.
const ID_PATTERN = /(?:edit\/)([^\/]]*)/;

const routes: Routes = [
  { 
    path: 'edit/:id', 
    component: ProductEditComponent, 
    resolve: {
      id: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => state.url.match(ID_PATTERN)[1]
    },
    data: { breadcrumb: { alias: 'ProductEdit' } }
  }
];
  • Related