Add dynamically created custom Angular components to layout in Nativescript


#1

I am trying to add a dynamically created custom Angular component to a GridLayout in NativeScript. I know how I can dynamically add the default non-Angular NativeScript components such a Label from tns-core-modules/ui/label, but it seems to be working different with Angular components.

I was following this post which describes how to do it in pure Angular. It seems to be almost working in NativeScript but not entirely. So far I am using a template like this:

 <GridLayout #grid>
 </GridLayout>

and then in the code I am attempting something like below:

@ViewChild('grid') gridRef:ElementRef;

public ngAfterViewInit() {

  let grid = this.gridRef.nativeElement;
  grid.addRow(new ItemSpec(1, GridUnitType.AUTO));
  grid.addColumn(new ItemSpec(1, GridUnitType.STAR));

  let componentFactory = this.cfr.resolveComponentFactory(MyCustomComponent);
  let componentRef = componentFactory.create(this.vcr.injector, null, grid);
  componentRef.instance.myproperty = 'some value'; // pass input

  this.appRef.attachView(componentRef.hostView); // add to ng component tree for change detection

  const component = (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0];
  grid.addChild(component);
}

After the final step, I do see that the grid has allocated the required space that the component requires, but nothing shows. If I comment out the last step, then indeed that space that is reserved is gone. I also confirmed that the rootNodes array has only one element.

Anyone has any idea as to what I might be missing? I guess the question is how can I take an Angular view and convert it to a NativeScript view, so I can perform the grid.addChild and also the actions below to assign the newly created component to a specific row/column.

GridLayout.setRow(component,0); // fix to grid row
GridLayout.setColumn(component,index); // fix to grid column

How will that then work?

Thanks!

P.S. I have opened this issue on Stack Overflow as well if someone prefers to answer there.


#2

Yes, it works differently with Angular components. It’s Angular’s rule and that’s how it understands components.

Can you create Playground with this?


#3

@manojdcoder Sure, here is the link to the playground project.

Now I also understand why extending ui/core/view didn’t give me the results I was expecting (like inheriting properties from NS Core’s View).


#4
  1. From row / col values won’t be assigned here as it’s a Angular component. It may be passed as input like you do for text property already.
<GridLayout #grid columns="auto" rows="auto">
        <MyLabel row="0" col="0" text="Static MyLabel"></MyLabel>
</GridLayout>
  1. Each Angular component is wrapped with a ViewBase, not sure how to actually access it. May be someone from {N} Angular project can answer it.