question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Request: Example of passing complex content projection

See original GitHub issue

Hi,

I’m looking to use NGXD to load dynamic components and content provided by a headless CMS like Contentful, but I’ve come into a bit of an issue where I’m struggling to figure out how to use content projection with the dynamically loaded components.

I have an X Column component that can host a number of predefined components, some of which are able to take complex content using ng-content. Is this something this package can handle? And is it possible to get an example?

Here’s some demo code I’ve created to explain the situation https://stackblitz.com/edit/angular-simple-dynamic-8emvyb?file=src/app/app.module.ts

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:19 (10 by maintainers)

github_iconTop GitHub Comments

2reactions
thekibacommented, May 12, 2020

Hello, @ChazUK

If you want to have using ng-content with dynamic components, you have to create projectableNodes by self. I’ll explain to you what do you need to do.

  1. You have to create an <ng-template> and put an <ng-content> in it.
@Component({
  selector: 'app-x-column',
  template: `
    <!-- 👇 place TemplateRef with NgContent here -->
    <ng-template #templateRef>
      <ng-content></ng-content>
    </ng-template>
  `
})
class XColumnComponent {}
  1. Then you have to get the TemplateRef using by @ViewChild() decorator.
@Component({
  selector: 'app-x-column',
  template: `
    <ng-template #templateRef>
      <ng-content></ng-content>
    </ng-template>
  `
})
class XColumnComponent {
  // 👇 getting access to the TemplateRef
  @ViewChild('templateRef', { 
    static: true, 
    read: TemplateRef
  })
  templateRef: TemplateRef<{}>;
}
  1. After that you need to create a projectableNodes. In order to do this you have to create a ViewRef of the TemplateRef and get rootNodes. Don’t forget to place the projectableNodes in *ngxComponentOutlet="content: projectableNodes".
@Component({
  selector: 'app-x-column',
  template: `
    <ng-template #templateRef>
      <ng-content></ng-content>
    </ng-template>
    <ng-container *ngxComponentOutlet="
      <!-- putting 👇 projectableNodes into the content of NgxComponentOutlet -->
      component; content: projectableNodes"></ng-container>
  `
})
class XColumnComponent {
  projectableNodes: any[][];

  @ViewChild('templateRef', { 
    static: true, 
    read: TemplateRef
  })
  set templateRef(t: TemplateRef<{}>) {
    // 👇 creating projectableNodes
    this.projectableNodes = [
      t.createEmbeddedView({}).rootNodes
    ];
  };
}
  1. Don’t forget to destroy the ViewRef, otherwise, this can lead to leaks.
this.viewRef = t.createEmbeddedView({});
// some later
this.viewRef.destroy();
1reaction
alQlagincommented, Oct 8, 2020

@xeladotbe this question is out of scope for this issue. In short you can’t apply any dicrectives to html content from CMS. But you can handle link click and use Router api. See this example https://stackblitz.com/edit/angular-inner-html-links?file=src/app/app.component.ts

Read more comments on GitHub >

github_iconTop Results From Across the Web

Content projection - Angular
Content projection is a pattern in which you insert, or project, the content you want to use inside another component. For example, you...
Read more >
Content Projection in Angular - Medium
Conditional Content Projection refers to creating a component into which you can conditionally project into one or more slots/directives.
Read more >
Content Projection in Angular with Ng-Content
The solution for the above-mentioned problem is Content Projection, i.e., we will project or send in the complete content from the parent and...
Read more >
Content Projection in Angular - This Dot Labs
The simplest way to do content projection is to use a single "slot" or area where we pass data in. Note that you're...
Read more >
From transclusion to content projection - Telerik Blogs
In more complex situations it might not be enough to simply use attribute bindings to pass in data, but there's the need for...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found