How to subscribe to a specific child route parameter?

Viewed 1178

I have these two route definitions, product list and product detail:

const routes: Routes = [
    ...
    {
        path: 'product',
        component: ProductListComponent,
        resolve: {
            products: ProductListResolverService
        },
        children: [
            {
                path: ':productcode',
                component: ProductDetailComponent,
                resolve: {
                    product: ProductDetailResolverService
                }
            },
            ...
        ]
    }
    ...

Inside the product list component I have a set of radio buttons to indicate which product is selected, while the router outlet displays the product detail component:

<div *ngFor="let product of Products" class="radio">
    <label>
        <input [(ngModel)]="SelectedProduct" 
            [value]="product" 
            (change)="RefreshDetail()" 
            name="selectedProduct" 
            type="radio"> 
            {{product.Name}} {{product.Code}}
    </label>
</div>
<router-outlet></router-outlet>

When the user clicks the radio button, the URL, the product detail component, and the radio button are synchronized correctly.

But when the user goes directly to a certain product URL, the URL and product detail component display the correct product, but the radio button doesn't. What I mean by going directly to a certain product URL is the user inputs the URL to the browser address bar and press enter.

I tried to get the value of :productcode from ActivatedRoute but it didn't work:

this.route.paramMap.subscribe(params => {
  let productcode = params.get("productcode");

  let product = this.Products.find(product => product.Code == productcode);

  if (!!product) {
    this.SelectedProduct = product;
  }
});

The paramMap.get("productcode") is always null. Probably because it is not available in the product list route, but in the child route, the product detail route.

I haven't found a way to subscribe to product detail route from product list component. Besides product detail route is not the only child of product list route.

How do I subscribe to a specific child route parameter?

2 Answers

One of the better way is to use the service and observable. So that, whenever the child component changes, the new data will get immediately reflected in the parent component (especially when u refresh the page you can retain your parent component status).

In your ProductDetailComponent,

import { Subscription } from 'rxjs';
import { Router, ActivatedRoute } from '@angular/router';
import { ProductService } from './product.service';


export class ProductDetailComponent {
    private subscription:Subscription;

    constructor(private activatedRoute:ActivatedRoute, private productService:productService){
    }

    public ngOnInit() {
      let vm = this;
      this.subscription = this.activatedRoute.params.subscribe(
          (param: any) => {
            if(typeof param['productcode'] !== 'undefined' && param['productcode'].trim !='' &&  typeof param['productcode']!=null){
               vm.productService.changedProductCode(param['productcode']);
            }
      });
    }
}

in your product.service.ts,

import { Subject } from 'rxjs/Subject'
import { Observable } from 'rxjs/Rx';

@Injectable()
export class myService {

  private productCode = new Subject<string>();

  productCodeChange$ = this.productCode.asObservable();
  changedProductCode(option:any){
        this.productCode.next(option);
  }
}

Now, to get the changed product id in your parent component,

ProductListComponent.ts

import { Subscription } from 'rxjs';
import { ProductService } from './product.service';

export class ProductListComponent {

    private subscription:Subscription;

    constructor(private productService:productService){

        this.productService.productCodeChange$.subscribe( /* get called on every child page changes*/
         code => {

        console.log(code); // you get your passed code value in 'code' variable

        let product = this.Products.find(product => product.Code == code);

        if (!!product) {
          this.SelectedProduct = product;
        }
    });
  }
}

try like this :

this.route.params.subscribe((params) => {

    let productcode = params['productcode'];

    let product = this.Products.find(product => product.Code == productcode);

    if (!!product) {
       this.SelectedProduct = product;
    }
});
Related