2

I have implemented a 'tree' list of categories for an Angular2 (Typescript) app I am developing. This component is supposed to allow you to be able to click on a category name (no matter whether it's a category or sub-category) and this will show products of the category.

My 'category-tree' component is a separate component and it is used recursively so I can traverse the category hierarchy correctly. For each category a span is generated with a 'click' event binded to it. When clicked I use the emit function to broadcast this information back to the parent component in order to update some variables there.

This functionality is working for top-level categories but the click is not working correctly when it is on a child category. The function which watches for the change does not receive any information.

Here is my code:

The function which logs out the information into my console. This is on the parent component:

changeCategory(event) {
        console.log(event);
    }

The html for the parent which holds the directive tag and the emit event name (categoryChange):

<div id='left-menu-wrapper'>
    <div id='left-menu'>
        <h1>{{title}}</h1>
        <h2>Categories</h2>
        <ul class="categories">
            <category-tree [categories]="categories" (categoryChange)="changeCategory($event)"></category-tree>
        </ul>
        <div *ngIf="selectedCategory">
            {{selectedCategory.name}}
        </div>
    </div>
    <div *ngIf="!contentLoaded" class='spinner'></div>
</div>
<product-view [product]="selectedProduct"></product-view>

The child component:

import { Component, Input, Output, EventEmitter, forwardRef } from 'angular2/core';

@Component({
    selector: 'category-tree',
    templateUrl: './app/views/category-tree.html',
    directives: [forwardRef(() => CategoryTree)],
    outputs: ['categoryChange']
})

export class CategoryTree {
    @Input() categories;
    public categoryChange:EventEmitter;
    constructor() {
        this.categoryChange =new EventEmitter();
    }

    categoryClick(category) {
        this.categoryChange.emit({
            value: category
        });
    }
}

And the recursive component html:

 <li *ngFor="#category of categories">
    <span (click)="categoryClick(category)" [class.selected]="category === selectedCategory">{{category.name}}</span>
    <ul *ngIf="category.sub_categories"  class='sub-category'>
        <category-tree [categories]="category.sub_categories"></category-tree>
    </ul>
</li>

As you can see, I bind a click event to each category which is that current category iteration. This calls an emit function in the category-tree class with that information and broadcasts it back. Again this works with a parent category but not a child.

My thinking is that as a child's direct parent component isn't the app.component.ts this may be causing an issue? I'm not sure.

Any ideas?

Thanks

James
  • 2,800
  • 7
  • 45
  • 81
  • If i understand correctly, you're HTML structure is not valid, since you are nesting an `
  • ` directly under another `
  • ` without a wrapping `
      `
  • – Tomer Jun 14 '16 at 13:53
  • 1
    I think you need @Output before ```public categoryChange:EventEmitter;``` so the component will have an event (categoryChange) on which you will add the handler changeCategory.. also I think when you are going more than 1 level deep in components it good to use singleton service – Denko Mancheski Jun 14 '16 at 13:56
  • I have fixed the nested
      issue. Thanks for pointing that one out. The original issue still stands though.
    – James Jun 14 '16 at 14:06