Carlos Cifuentes
AngularJS → Angular reference

$compile in modern Angular

Angular compiles templates at build time, so there is no way to compile an HTML string at runtime. Dynamic UI is built by choosing among components that already exist.

Before · AngularJS
app.directive('widgetHost', function ($compile) {
  return {
    scope: { type: '<', data: '<' },
    link: function (scope, element) {
      var tag = scope.type + '-widget';
      var html = '<' + tag + ' data="data"></' + tag + '>';
      element.append($compile(html)(scope));
    }
  };
});
After · Angular
const WIDGETS: Record<string, Type<unknown>> = {
  chart: ChartWidgetComponent,
  table: TableWidgetComponent,
};

@Component({
  selector: 'app-widget-host',
  imports: [NgComponentOutlet],
  template: `<ng-container [ngComponentOutlet]="component()"
               [ngComponentOutletInputs]="{ data: data() }" />`,
})
export class WidgetHostComponent {
  type = input.required<string>();
  data = input<unknown>();
  component = computed(() => WIDGETS[this.type()]);
}

What changes

  • A map from a key to a component class replaces the HTML string built by concatenation.
  • NgComponentOutlet renders the chosen component from the template and passes its inputs.
  • ViewContainerRef.createComponent does the same from code and returns a ComponentRef, with setInput to pass data.

Migration tip. Find out early if any templates come from a database or a backend response. Those cannot be ported as they are and need a redesign: a fixed set of components driven by data.

Related

Planning a migration or a micro-frontend platform?

In a 20-minute call you describe your situation and I tell you how I'd approach it. If it isn't worth doing yet, I'll say so.

Message me on LinkedIn