wishtack / wishtack-steroids

Frontend on Steroids: Reactive Component Loader, RxJS Scavenger...
https://wishtack.io
MIT License
96 stars 16 forks source link

Find component by selector with IVY enabled #200

Open jotwea opened 4 years ago

jotwea commented 4 years ago

I searched for a way to lazy load modules and create components by only knowing its selector. I found this library and was quite amazed - it works perfect (also with AoT). But then I tried to apply it to my Angular 9 project with Ivy enabled and recognized that it always creates the same component. Then I had a look into the implementation and saw that for the Ivy variant the selector is ignored:

https://github.com/wishtack/wishtack-steroids/blob/690412ca94d069ba9cc374489ebb07952b8ee9b5/packages/reactive-component-loader/src/lib/reactive-component-loader.service.ts#L118

So without Ivy the correct component is searched from the entryComponents array but with Ivy enabled it always creates first of the bootstrapComponents. Do you have plans to apply finding the right component by its selector also to the Ivy variant? And do you have plans to update your library to Angular 9?

BluefishTom commented 4 years ago

I'm also having trouble with Angular 9. With:

editorLocation = { moduleId: 'lazy-module', selector: 'app-lazy-component' };

I get:

Component '<app-lazy-component>' not found.

EngelaereAntoine commented 4 years ago

I did make it work with Angular 9 and Ivy by replacing the entryComponents by bootstrap int the lazy loaded component's module.

pie-chart.component.ts

@NgModule({
  declarations: [PieChartComponent],
  imports: [CommonModule, AngularSvgIconModule, DonutModule],
  // entryComponents: [PieChartComponent],
  bootstrap: [PieChartComponent],
  exports: [PieChartComponent]
})
export class PieChartModule {
.....
}

@Component({
  selector: pieChart,
  templateUrl: './pie-chart.component.html',
  styleUrls: ['./pie-chart.component.scss']
})

I've my selector declared in a different file :

widget-loader.service.ts

export const pieChart = 'app-pie-chart';
export const gaugeChart = 'app-gauge-chart';

export function hash(widgetType: WidgetType): ComponentLocation {
  switch (widgetType) {
    case WidgetType.pieChart:
      return {
        moduleId: pieChart,
        selector: pieChart
      };
    case WidgetType.gaugeChart:
      return {
        moduleId: gaugeChart,
        selector: gaugeChart
      };
  }
}

@Injectable({
  providedIn: 'root'
})
export class WidgetLoaderService {
  public locate(widget: Widget): ComponentLocation {
    return hash((widget.attributes as WidgetData)._type);
  }
}