6

I am trying to use a component, the template of which refers to another instance of the same component within it.

The model is like this:

class Item {
  String name;
  Item(this.name);
}

class Box extends Item {
  Box(String name) : super(name);
  List<Item> contents = [];
}

Based on the above, data is created thus:

myBox = new Box('top box');
myBox.contents.add(new Item('level 2 - 1'));
myBox.contents.add(new Item('level 2 - 2'));
Box myBox2 = new Box('inner box');
myBox2.contents.add(new Item('level 3 - 1'));
myBox2.contents.add(new Item('level 3 - 2'));
myBox.contents.add(myBox2);

Represented as JSON it would look like this:

{
  "name": "top box",
  "contents": [
    {"name": "level 2 - 1"},
    {"name": "level 2 - 2"},
    {"name": "inner box",
      "contents": [
        {"name": "level 3 - 1"},
        {"name": "level 3 - 2"}
      ]
    }
  ]
}

The component dart (box_component.dart):

@Component(
    selector: 'box-component',
    templateUrl: 'box_component.html',
    directives: const[CORE_DIRECTIVES]
)
class BoxComponent implements OnInit {
    @Input()
    Box box;
    List contents =[];

ngOnInit() {
    contents = box.contents;
}
 isBox(Item itm) => (itm is Box);
}

The component template (box_component.html):

<div *ngIf="box != null" style="font-weight: bold">{{box.name}}</div>
<div *ngFor="let item of contents">
  {{item.name}}
  <div *ngIf="isBox(item)">
    This is a box
    <box-component [box]="item"></box-component>
  </div>
  <div *ngIf="!isBox(item)">
    This is an item
  </div>
</div>

Note that another instance of box-component is nested within the top level box-component However, when rendered, only contents of the top level box are rendered, and not the ones that are contained in the box that is nested within.

It looks like this:

top box
level 2 - 1
This is an item
level 2 - 2
This is an item
inner box
This is a box
This is an item

Is there a way to achieve a recursive nested rendering?

Hesh
  • 413
  • 1
  • 3
  • 11
  • 2
    `*ngFor` and `*ngIf` on the same element is invalid. You should get an error for that. `*ngIf` is redundant anyway because ’*ngFor` won't render anything for empty arrays. Besides that there is nothing special about nested components. – Günter Zöchbauer Dec 19 '17 at 19:24
  • You are right, @GünterZöchbauer. It was throwing some errors, and I was ignoring them. Thanks for pointing out, I am correcting the details in my question. However, I am still not getting the contents of the nested component. – Hesh Dec 19 '17 at 19:35
  • 1
    Is the directives list correct above? You only say that BoxComponent uses CORE_DIRECTIVES which isn't right you are also trying to use a BoxComponent. – Ted Sander Dec 19 '17 at 21:05
  • Thank you, @TedSander. You have nailed it. I added, BoxComponent also as one of the directives of BoxComponent itself, and it worked. Please, will you, write your response as an answer so that I can declare it as accepted. Thanks again. – Hesh Dec 19 '17 at 22:10

1 Answers1

5

Any directives that a template uses must be declared in the directives list. This includes itself if it wants to recursively use itself. So in your case the @Component annotation should be:

@Component(
    selector: 'box-component',
    templateUrl: 'box_component.html',
    directives: const[CORE_DIRECTIVES, BoxComponent]
)
class BoxComponent
Ted Sander
  • 1,899
  • 8
  • 11