Juggernaut
Juggernaut

Reputation: 806

How do I render a component inside another dynamically loaded component in Angular?

I am trying to make a custom Grid component, in which I want to render/pass other components. I created a Grid component and I'm dynamically loading it in my dashboard.component.ts.

Here is my Grid's template.

<div nz-row *ngFor="let row of grid; index as i;">
    <div nz-col *ngFor="let col of row; index as j;">
      <div>
        <ng-template name="{{i}}{{j}}"></ng-template>
      </div>
    </div>
</div>

The directive.

@Directive({
  selector: 'ng-template[name]'
})
export class CustomGridDirective {
  @Input() name: string;

  constructor(public viewContainerRef: ViewContainerRef) { }
}

My custom-grid.component.ts,

export class CustomGridComponent implements OnInit {

  @Input() grid: any;
  @ViewChildren(CustomGridDirective) gridContainer: QueryList<CustomGridDirective>;
  
  constructor() {}
  
  ngOnInit() {
  }
}

Dashboard.component.ts, where I'm dynamically loading my Grid component.

async customGrid(){
  const {CustomGridComponent} = await import('../custom-grid/custom-grid.component');
  const customGridFactory = this.cfr.resolveComponentFactory(CustomGridComponent);
  let {instance} = this.anchor1.createComponent(customGridFactory, null, this.injector);
  instance.grid = [
    ['1', '2', '3']
  ]
  return instance
}

ngAfterViewInit() {
  this.customGrid().then( component => console.log(component.gridContainer));
}

Now, I'm unable to access component.gridContainer or even component.grid. Both return, undefined.

Say I have a dashboard-widget-1.component, how do I dynamically render it inside the custom-grid component? I was trying to approach the ViewChildren's query list and try to render the component inside.

But I get component.gridContainer and component.grid, both, as undefined. How can I dynamically render components, such as dashboard-widget-1.component and dashboard-widget-2.component in my Grid Component (which I have dynamically loaded)?

I'm stuck since days, any help will be greatly appreciated.

Upvotes: 2

Views: 1114

Answers (1)

yurzui
yurzui

Reputation: 214047

It's undefined because there wasn't any change detection cycle executed on that component yet.

componentRef.changeDetectorRef.detectChanges();

const widgetFactory = this.cfr.resolveComponentFactory(CustomWidgetComponent);
instance.galleryContainer.forEach(target => {
  target.viewContainerRef.createComponent(widgetFactory, null, this.injector)
});

Also if you want to lazy load component then make sure imported file contains NgModule which describes all dependant declarations:

custom-grid.components.ts

@Component({
  ...
})
export class CustomGridComponent implements OnInit {
  ...
}
... 
@NgModule({
  imports: [
    CommonModule,
  ],
  declarations: [CustomGridComponent, CustomGridDirective],
})
export class CustomGridModule { }

Forked Stackblitz

Upvotes: 1

Related Questions