2

I trying to show nested object to select main or children object to add other inside

const categories = [
  {
    id: 1,
    title: 'Tecnology',
    subCategory: [
      {
        id: 3,
        title: 'JavaScript',
        subCategory: [
          {
            id: 4,
            title: 'Angular',
          },
        ],
      },
      {
        id: 5,
        title: 'C#',
      },
    ],
  },
  {
    id: 2,
    title: 'Health',
  },
];

my html

<div>
  <a
    class="dropdown-item"
    *ngFor="let category of categories"
  >

    {{ category.title }}
    <span
      *ngFor="let subCategory of category.subForumCategories"
    >
      > {{ subCategory.title }}
    </span>
  </a>
</div>

expected result

Tecnology
Tecnology > JavaScript
Tecnology > javaScript > Angualr
Tecnology > C#
Health

but i got the result

Tecnology > javaScript > C#
Health

in stackblitz: https://stackblitz.com/edit/angular-ivy-jfkszn?file=src/app/app.component.html

3

2 Answers 2

2

Probably better off working this out in typescript, and then iterating an array of strings instead of the objects. Angular templates are great for a lot of stuff, but this is probably starting to push it.

Here is an example of what you could have in ts

var categories = [{
    id: 1,
    title: "Technology",
    subCategory: [{
        id: 3,
        title: "JavaScript",
        subCategory: [{
          id: 4,
          title: "Angular"
        }]
      },
      {
        id: 4,
        title: "C#"
      }
    ]
  },
  {
    id: 2,
    title: "Health"
  }
];


getList();

function getList() {
  var list = extractSubCategories(categories);
  console.log(list);
}

function extractSubCategories(categories) {
  var list = [];
  for (var c of categories) {
    if (c.subCategory) {
      list.push(`> ${c.title}`);
      list.push(...extractSubCategories(c.subCategory).map(sc => `> ${c.title} ${sc}`));
    } else {
      list.push(`> ${c.title}`);
    }
  }
  return list;
}

template:

<div>
  <a class="dropdown-item" *ngFor="let category of getList()" > {{category}} </a>
</div>
Sign up to request clarification or add additional context in comments.

2 Comments

is the getList() function in html efficient? it will be doing the loop, pushes, and map every digest cycle. I would double check performance on larger objects.
@rhavelka with the information provided in this question, yes it would be efficient. If the question stated that the iterable list was 10000+ items, then maybe you would change strategy. Not like this is going to run every tick, so it should meet the purpose.
1

You can create a recursive component. Then you can just pass in the object to display the way you want.

component.ts

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

@Component({
  selector: 'categories',
  template: `
     <div *ngFor="let category of categories">
        <div>
          {{titleHistory}} {{category.title}}
        </div>
        <categories[categories]="category.subCategory" 
                   [title]="titleHistory + category.title" 
                   [depth]="depth+1" 
                   *ngIf="category.subCategory"></categories>
    </div>`,
})
export class CommentComponent implements OnInit {
  @Input() categories: Categories;
  @Input() title: string = '';
  @Input() depth: number = 0;

  titleHistory = '';

  ngOnInit() {
    this.titleHistory = this.depth === 0 ? this.title : (this.title + ' > ');
  }
}

app.component.html

<categories [categories]="categoriesData"></categories>

stackblitz

Edit: updated stackblitz with more options

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.