Home > database >  Angular generate template with dynamic depth of object
Angular generate template with dynamic depth of object

Time:11-05

I have an object Item like that:

{
    name: string;
    parent: Item;
}

and I want to display all items till the parent attribute is empty. Example:

{
  name: "child3",
  parent: {
    name: "child2",
    parent: {
      name: "child1",
      parent: {
        name: "parent",
        parent: undefined
      }
  }
}

should generate html like that:

<a>child3</a> <a>child2</a> <a>child1</a> <a>parent</a>

How can I do that?

    <a [...] *ngIf="item">{{ item.name }}</a>
    <a [...] *ngIf="item.parent">{{ item.parent.name }}</a>
    <a [...] *ngIf="item.parent.parent">{{ item.parent.parent.name }}</a>
    [...]

Something like that would work, but not if the depth is unknown.

So how can I write a template that does exactly that?

CodePudding user response:

SOLUTION 1

You can create a component with a nesting items (recursion):

@Component({
  selector: 'component',
  template: `

<!-- Show name -->
<a href="">{{item.name}}</a>

<!-- Show  parent -->
<component *ngIf="item.parent" [item]="item.parent">
</component>
  `
})
export class Component {
  @Input()
  item: any;
}

And just use it in your component like:

const obj = {
  name: "child3",
  parent: {
    name: "child2",
    parent: {
      name: "child1",
      parent: {
        name: "parent",
        parent: undefined
      }
  }
}

<component[item]="obj">
</component>

SOLUTION 2

Would be to go through an object, and make an array of names .Like:

const obj = {
  name: "child3",
  parent: {
    name: "child2",
    parent: {
      name: "child1",
      parent: {
        name: "parent",
        parent: undefined
      }
    }
  }
}


const getNames = (obj) => {
  
  let currentObject = obj;

  const names = [];

  while (true) {
    if (!currentObject) return names;
    names.push(currentObject.name);
    currentObject = currentObject.parent;
  }
  
}

// Here you will get ['child3', 'child2', 'child1', 'parent']
const names = getNames(obj);

// And in the template you can just in a for loop show them
  • Related