Search code examples
javascriptangulartypescriptangular2-routingdynamic-routing

I want to make a Dynamic Routing by picking up the SELECTIVE ELEMENTS FROM ARRAY OF OBJECTS --- TYPESCRIPT


1. all-trades.component.ts

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

@Component({
  selector: 'app-all-trades',
  templateUrl: './all-trades.component.html',
  styleUrls: ['./all-trades.component.css'],
})
export class AllTradesComponent implements OnInit {

// This is my Array of Object

  crops = [
    {
      name: 'Rice',
      checked: true,
      subCategory: [
        {
          id: 1,
          name: 'Basmati',
          isActive: true,
        },
        {
          id: 2,
          name: 'Ammamore',
          isActive: true,
        },
      ],
    },
    {
      name: 'Wheat',
      checked: true,
      subCategory: [
        {
          id: 1,
          name: 'Durum',
          isActive: true,
        },
        {
          id: 2,
          name: 'Emmer',
          isActive: true,
        },
      ],
    }, {
      name: 'Barley',
      checked: true,
      subCategory: [
        {
          id: 1,
          name: 'Hulless Barley',
          isActive: true,
        },
        {
          id: 2,
          name: 'Barley Flakes',
          isActive: true,
        },
      ],
    }
  ]



  onChange(event, index, item) {
    item.checked = !item.checked;
    console.log(index, event, item);
  }

  constructor(private route: ActivatedRoute) { }

  ngOnInit(): void { }

  
}

2. all-trades.component.html

<app-header></app-header>
<div
  fxLayout="row"
  fxLayout.lt-md="column"
  fxLayoutAlign="space-between start"
  fxLayoutAlign.lt-md="start stretch"
>
  <div class="container-outer" fxFlex="20">
    <div class="filters">
      <section class="example-section">
        <span class="example-list-section">
          <h1>Select Crop</h1>
        </span>
        <span class="example-list-section">
          <ul>
            <li *ngFor="let crop of crops">
              <mat-checkbox
                [checked]="crop.checked"
                (change)="onChange($event, i, crop)"
              >
                {{ crop.name }}
              </mat-checkbox>
            </li>
          </ul>
        </span>
      </section>

      <section class="example-section">
        <span class="example-list-section">
          <h1>Select District</h1>
        </span>
        <span class="example-list-section">
          <ul>
            <li *ngFor="let district of districts">
              <mat-checkbox>
                {{ district.name }}
              </mat-checkbox>
            </li>
          </ul>
        </span>
      </section>
    </div>
  </div>
  <div class="content container-outer" fxFlex="80">
    <mat-card
      class="crop-card"
      style="min-width: 17%"
      *ngFor="let crop of crops"
      [hidden]="!crop.checked"
    >
    <!-- I tried the logic here to navigate to sub-Category Array by its id.
    But I failed -->
      <a
        [routerLink]="['/all-trades', crop.id]"
        routerLinkActive="router-link-active"
      >
        <mat-card-header>
          <img
            mat-card-avatar
            class="example-header-image"
            src="/assets/icons/crops/{{ crop.name }}.PNG"
            alt="crop-image"
          />
          <mat-card-title>{{ crop.name }}</mat-card-title>
          <mat-card-subtitle>100 Kgs</mat-card-subtitle>
        </mat-card-header>
      </a>
      <mat-card-content>
        <p>PRICE</p>
      </mat-card-content>
    </mat-card>
  </div>
</div>

<app-footer></app-footer>

enter image description here

Here You guys can see on my webpage there is couples of cards named as "RICE", "WHEAT", "BARLY" All just I want to do is by clicking on RICE my code should navigate to another component page and display the name of subCategory name from my Array of Object. Similarly, it should also work for "WHEAT" and "BARLEY" as well Example: When I click on Wheat Card it should navigate to different page and display the name of subCategory of Wheat section.

crops = [
    {
      name: 'Rice', <---- 1. Go here
      checked: true,
      subCategory: [ <-- 2. Go to subCategory and fetch the name of the "RICE" on different Page
        {
          id: 1,
          name: 'Basmati',
          isActive: true,
        },
        {
          id: 2,
          name: 'Ammamore',
          isActive: true,
        },
      ],
    },
    {
      name: 'Wheat',
      checked: true,
      subCategory: [
        {
          id: 1,
          name: 'Durum',
          isActive: true,
        },
        {
          id: 2,
          name: 'Emmer',
          isActive: true,
        },
      ],
    }, {
      name: 'Barley',
      checked: true,
      subCategory: [
        {
          id: 1,
          name: 'Hulless Barley',
          isActive: true,
        },
        {
          id: 2,
          name: 'Barley Flakes',
          isActive: true,
        },
      ],
    }
  ]

Solution

  • You can use BehaviorSubject to do the same

    app-routing.component.ts // define route path

     const routes: Routes = [
     //other routes
     { path:'crop/:name', component:CropComponent}
     ]
     
    

    crop.ts //model the interface for crop

    export class crop{
      name: string;
      checked: boolean;
      subCategory:Subcategory[];
    

    }

    export class Subcategory{
       id: number;
       name: string;
       isActive: boolean;
    }
    

    service.ts //create a subject and define getter and setter methods

    export class CropService {
    private selectedCrop= new BehaviorSubject<Crop>(null);
    
    setCrop(crop:Crop){
     this.selectedCrop.next(crop);
     }
    
    getCrop(){
    return this.selectedCrop.asObservable().pipe(skipWhile(val=> val === null)); 
    }
    

    }

    all-trades.component.html //Replace the routerLink with click event

    <mat-card
      class="crop-card"
      style="min-width: 17%"
      *ngFor="let crop of crops"
      [hidden]="!crop.checked"
    >
    
      <a
       (click)="onSelect(crop)"
        routerLinkActive="router-link-active"
      >
        <mat-card-header>
          <img
            mat-card-avatar
            class="example-header-image"
            src="/assets/icons/crops/{{ crop.name }}.PNG"
            alt="crop-image"
          />
          <mat-card-title>{{ crop.name }}</mat-card-title>
          <mat-card-subtitle>100 Kgs</mat-card-subtitle>
        </mat-card-header>
      </a>
      <mat-card-content>
        <p>PRICE</p>
      </mat-card-content>
    </mat-card>
    

    all-trades.component.ts //emit the selected crop and route to the same component

    constructor(private service: Cropservice, private router:Router){}
    
    onSelect(selectedCrop:Crop){
    this.service.setCrop(selectedCrop);
    this.router.navigateByUrl(`crop/${crop.name}`);
    }
    

    crop.component.ts // subscribe to the subject and store the crop data locally

    crop: Crop
    export class CropComponent implements OnInit{
    
    ngOnInit(){
    this.service.getCrop().subscribe((selectedCrop:Crop)=>this.crop = 
    selectedCrop)
    }
    }
    

    crop.component.html

    <div *ngFor="let category of crop.subCategory">{{category.id}}</div>