1

I have defined categories and sub-categories for products in my angular app. I intend to have a tree structure for the categories whereby, a top-level category can theoretically have infinite number of nested sub-categories.

When I navigate to the details page of a category, I also want to display the sub-categories of that particular category and repeat the pattern for all the nested levels.

My problem is that only links for the top-level categories are working while links to sub-categories are not working. My setup for the app is as follows

For app-routing.module.ts

const routes: Routes = [
  {
    path:'security',
    loadChildren: () => import('./security/security.module').then(mod=>mod.SecurityModule)
  },
  {
    path:'',
    component: DefaultComponent,
    children: [
      {
        path: 'categories',
        loadChildren: () => import('./categories/categories.module').then(mod=>mod.CategoryModule)
      },
      {
        path: 'products',
        loadChildren: () => import('./products/products.module').then(mod=>mod.ProductsModule)
      }
    ]
  },
  {
    path: '**', 
    component: PageNotFoundComponent
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Then for category-routing.module.ts


const routes: Routes = [
  {
    path: ':id',
    component: CategorydetailsComponent
  },
  {
    path: '',
    component: CategorylistComponent
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class CategoryRoutingModule { }

The file categorylist.component.ts has

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

  categories : Category[] = [];
  category: Category = new Category();
  
  constructor(private categoryService: CategoryserviceService,
              private router:Router
              ) {  }

  ngOnInit(): void {

    this.getTopLevelCategories();

    //can create, update, delete collections
    this.canManageCollections();
    // window.alert(this.canManageCollections())
  }
  
  getTopLevelCategories(){
    this.categoryService.getTopLevelCategories().subscribe((data) =>{
      this.categories = data;
    });
  }  
}

Then in the file categorydetails.component.ts, I have

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

  category: Category = new Category;
  subCategories: Category[] = [];


  private id: string | null;

  constructor(
    private categoryService: CategoryService, private route: ActivatedRoute
  ) {
    this.id = route.snapshot.paramMap.get('id');
  }

  ngOnInit(): void {

    this.CategoryService.getCategoryDetails(this.id).subscribe(categoryDetails => {
        this.category = categoryDetails;
      });

    this.categoryService.getSubCategories(this.id).subscribe(subCategories => {

      this.subCategories = subCategories;
    });

  }
}

In the categorylist.component.html, this is where I display the top-level categories

<div class="row">
  <ng-template [ngIf]="categories && categories.length > 0" [ngIfElse]="noCategories">
    <div class="col-md-3 col-xs-6 col-12" *ngFor="let category of categories">
      <a [routerLink]="['/categories', category.id]">
<!--      <a href="/categories/{{ category.id }}">-->
        <div class="collection-main">
          <img src="assets/images/book.svg" alt="collection-logo" />
          <h2 class="text-container">
            <span>
              {{ category.code }}
              {{ category.name }}
            </span>
          </h2>
        </div>
      </a>
    </div>
  </ng-template>
  <ng-template #noCategories>
    <div class="alert alert-info" role="alert">{{ 'categories.No_categories_found' | translate}}</div>
  </ng-template>
</div>

Finally in the categorydetails.component.html. This is where I display the sub-categories.

<div class="row">
  <div class="col-lg-12">
    <div class="category-details">
      <h1>{{ 'categories.Description' | translate }}</h1>
      <p>{{ category.category_description }}</p>
    </div>
  </div>
  <div class="col-12">
    <h1 class="subcollection-heading">{{ 'categories.Sub-categories_in' | translate }} {{ category.name }}</h1>
  </div>

  <ng-template [ngIf]="subCategories.length > 0" [ngIfElse]="noChildren">
    <div class="col-md-3 col-xs-6 col-12" *ngFor="let subCategory of subCategories">
      <a [routerLink]="['/categories', subCategory.id]">
        <div class="collection-main">
          <img src="assets/images/subcollection.svg" alt=""/>
          <h2 class="text-container">
            <span>
              <ng-template>{{ subCategory.code }}</ng-template>
              {{ subCategory.name }}
            </span>
          </h2>
        </div>
      </a>
    </div>
  </ng-template>

  <ng-template #noChildren>
    <div class="alert alert-info">{{ 'categories.No_sub-categories_found' | translate}}</div>
  </ng-template>

</div>

default.component.html file

<div class="connect-container align-content-stretch d-flex flex-wrap">

  <div class="page-sidebar">
    <app-sidebar></app-sidebar>
  </div>

  <div class="page-container">

    <div class="page-header">
      <app-header></app-header>
    </div>

    <div class="page-content">
      <div class="main-wrapper">

        <router-outlet></router-outlet>
      </div>
    </div>
  </div>
</div>

With this setup, the links in categorylist.component.html are working but links in categorydetails.component.html do not work. However, I observe that the browser URL changes but the page content remains the same.

MrCodingB
  • 2,284
  • 1
  • 9
  • 22
Otuoma Sanya
  • 141
  • 1
  • 4
  • 10
  • How does the html of your `DefaultComponent` looks like? Did you include the `router-outlet` tag? Or did you just render the content of app list through `app-categorylist` ? – W.S. May 29 '22 at 20:06
  • @W.S. Yes, Have updated my question with `default.component.html` – Otuoma Sanya May 30 '22 at 04:32
  • 1
    At first sight, the setup seems correct, although it's difficult to say without having a working sample repository. You can enable tracing on the RouterModule `RouterModule.forRoot(routes, {enableTracing: true})`. Maybe this will tell you something more, what happens when you click on the link to route to the detail component. – W.S. May 30 '22 at 06:52
  • 1
    You can try to use a subscription to the router `ngOnInit() { this.route.paramMap.subscribe(params => { this.id = params.get("id") }) }` instead of getting snapshot in constructor `this.id = route.snapshot.paramMap.get('id');`. But of course, it would be great to have stackblitz sample to provide a more accurate recommendation. – Nataly Chkhan May 30 '22 at 08:37

0 Answers0