0

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.

1

1 Answer 1

1

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/.../'
// or 'example.com/.../edit/:id?foo=...'
// or 'example.com/.../edit/:id/...?foo=...'
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/edit/1
    const url = state.url;

    // ['edit', '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 only need the initial value and know it 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/.../'
// or 'example.com/.../edit/:id?foo=...'
// or 'example.com/.../edit/:id/...?foo=...'
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' } }
  }
];
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.