Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 7 Dynamic Content Projection

I need to be able to tell an angular component to render another angular component based on dynamic data. I think this needs content projection, but I can only make content projection work in simple cases.

Example scenario

I have the following table data in vanilla TypeScript:

const headings = [
  { id: 'cat', label: 'Cat' },
  { id: 'nameIt', label: 'Type the name' }
]

const data = [
  { cat: 'Tabby', nameIt: (name) => updateTabbysName(name) },
  { cat: 'Ginger', nameIt: (name) => updateGingersName(name) },
]

I also have four Angular components:

  • simple-span which renders text in a span. In this case, it will render the cat field.
  • text-input which renders a text input. In this case, it will render a basic HTML input which will call the nameIt callback when the user inputs text.
  • my-special-cat-table which will provide the headings and data variables and is allowed to know about text-input and simple-span
  • generic-table which is responsible for rendering table DOM elements. It is not allowed to know that text-input or simple-span exist.

The aim is to have generic-table completely blind to the cell render components

Is it possible to achieve this in Angular 7?

like image 814
Tom Riglar Avatar asked Mar 14 '19 17:03

Tom Riglar


Video Answer


1 Answers

There is *ngComponentOutlet directive for declarative dynamic components: https://angular.io/api/common/NgComponentOutlet

Keep in mind you need to have them all in entryComponents so Injector would know about them and their factories. If you post more code, we can try to figure out the exact solution.

Basically, what it does is resolves a factory then creates it with injector and adds to the view:

    const componentFactory = this.componentFactoryResolver
        .resolveComponentFactory(component);

    this.componentRef = this.viewContainerRef.createComponent(componentFactory);

You can write your own abstraction with similar idea and have it work with any component you want. Strange that people here say that it's impossible now.

like image 173
waterplea Avatar answered Oct 13 '22 14:10

waterplea