admin管理员组

文章数量:1334337

I need to be able to tell an angular ponent to render another angular ponent 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 ponents:

  • 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 pletely blind to the cell render ponents

Is it possible to achieve this in Angular 7?

I need to be able to tell an angular ponent to render another angular ponent 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 ponents:

  • 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 pletely blind to the cell render ponents

Is it possible to achieve this in Angular 7?

Share edited Mar 14, 2019 at 19:02 Magnus Melwin 1,5171 gold badge21 silver badges34 bronze badges asked Mar 14, 2019 at 17:13 Tom RiglarTom Riglar 1971 silver badge9 bronze badges 4
  • Short answer is no. – Randy Casburn Commented Mar 14, 2019 at 17:16
  • Right now, there is no solution that would be 100% generic. – user4470482 Commented Mar 14, 2019 at 17:17
  • I think you are asking for something ngx-datatable and Angular Material Data Table already doing. – HirenParekh Commented Mar 19, 2019 at 17:59
  • 1 For anyone interested in where I went with this... We ended up switching to React. The fundamental difference is that React is JavaScript through the entire ponent tree, whereas Angular has a template language layer between each ponent. This means that passing an unknown/dynamic ponent down the tree is React is trivial, whereas in Angular it isn't currently possible. Or at least not in a generic way. – Tom Riglar Commented Nov 7, 2019 at 14:43
Add a ment  | 

3 Answers 3

Reset to default 1

There is *ngComponentOutlet directive for declarative dynamic ponents: https://angular.io/api/mon/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 ponentFactory = this.ponentFactoryResolver
        .resolveComponentFactory(ponent);

    this.ponentRef = this.viewContainerRef.createComponent(ponentFactory);

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

You can evaluate creating Reusable Components with NgTemplateOutlet. Just a suggestion.

Take a look at this example.

What you want to aplish is to use content projection in a loop. Here is an example for Angular Material:

…
<ng-container *ngFor=”let column of displayedColumns” matColumnDef=”{{column.id}}”>
   <th mat-header-cell *matHeaderCellDef mat-sort-header>{{column.name}}</th>
   <td mat-cell *matCellDef=”let row”>
      {{row[column.id]}}
   </td>
</ng-container>
…

As you can see by usage code, you can create multiple templates and bine them in whatever way you want:

<my-ponent …
[itemTemplate]=”itemTemplate”>
   <ng-template let-item #itemTemplate>
      column id: {{item.column.id}}
      value: {{item.value}}
   </ng-template>
</my-ponent>

source

本文标签: javascriptAngular 7 Dynamic Content ProjectionStack Overflow