Search code examples
dartangular-dart

Recursively using a Component


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?


Solution

  • 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