I'm trying to load different 'parent' components and inject route content into these different parent components by targeting ng-content
in each parent component. Essentially, each parent component handles the navigation and other boilerplate stuff based on device widths (small/mobile, medium/tablet, and large/desktop).
The content generated for each route in my application needs to get transcluded (injected) into the parent components. The content for each route targets specific injection points using ng-content
.
I'm able to swap out the parent components using <ng-container *ngComponentOutlet="ResponsiveComponent;"></ng-container>
. The problem is my route-generated content is not getting injected into the targeted ng-content
locations in each parent component.
Here's the code for swapping out parent components. AppPageComponent
extends ResponsiveComponent
which monitors device width based on media queries.
@Component({
selector: 'app-page',
template: `
<ng-container *ngComponentOutlet="ResponsivePageComponent;"></ng-container>
`,
styleUrls: [ './page.component.scss'],
providers: []
})
export class AppPageComponent extends ResponsiveComponent implements OnInit, OnDestroy
{
ResponsivePageComponent;
constructor(
injector: Injector,
zone: NgZone)
{
super(zone);
}
ngOnInit()
{
this.IsSmallEnvironmentStream
.subscribe
(
(isSmall: boolean) =>
{
if (isSmall)
{
this.ResponsivePageComponent= AppPageSmallComponent;
}
},
(err) => { },
() => {}
);
this.IsMediumEnvironmentStream
.subscribe
(
(isMedium: boolean) =>
{
if (isMedium)
{
this.ResponsivePageComponent = AppPageMediumComponent;
}
},
(err) => { },
() => {}
);
this.IsLargeEnvironmentStream
.subscribe
(
(isLarge: boolean) =>
{
if (isLarge)
{
this.ResponsivePageComponent = AppPageLargeComponent;
}
},
(err) => { },
() => {}
);
}
}
Angular's documentation for NgComponentOutlet shows you can target optional list of projectable nodes to insert into the content (ng-content) placeholders. I followed the examples from Angular's documentation and was able to inject text nodes into the different ng-content
placeholders in my parent components and it works for my small/medium/large parent components.
How do I get the content from my routes to inject into these different placeholders? It seems like I'm really close to getting this to work. I can inject in essence static content into the palceholders, but I can not figure out how to inject the content generated by routes into the placeholders.
UPDATE - 07/25/2017
I created this plunker demonstrating this scenario (https://plnkr.co/edit/hOwRX1Ml6gX0S8em6nd5?p=preview).
In the plunker, page-wrapper
component uses ngComponentOutlet to load small/medium/large component depending upon device width. page-wrapper component is injecting static content into the placeholders in each small/medium/large component instead of injecting route content from page 1.
My objective is to have a page wrapper component to handle responsive needs like different navigation elements for small/medium/large responsive designs.
So, how can 'static' content be injected into dynamically loaded component's ng-content
placeholders yet route generated content is not being injected into ng-content
placeholders?
Thanks for your help.
1) You can define ng-content
places in your PageWrapperComponent and transclude them to dynamic component
page-wrapper.component.html
<ng-container *ngComponentOutlet="ResponsiveComponent;
content: [[el1],[el2]]"></ng-container>
<div #el1>
<ng-content></ng-content>
</div>
<div #el2>
<ng-content select="[named-injection-point]"></ng-content>
</div>
Plunker Example
2) You can also use template reference variables(or custom directive) in parent component and @ContentChild
in PageWrapperComponent
to get transcluding sections.
page-one.component.html
<page-wrapper>
<section #mainPoint>
<h2>Page One</h2>
</section>
<section #namedPoint>
<h3>Page One Content:</h3>
<p>Lorem ipsum dolor.</p>
</section>
</page-wrapper>
page-wrapper.component.ts
@ContentChild('mainPoint') mainPoint;
@ContentChild('namedPoint') namedPoint;
page-wrapper.component.html
<ng-container *ngComponentOutlet="ResponsiveComponent;
content: [[mainPoint.nativeElement],[namedPoint.nativeElement]]"></ng-container>
Plunker Example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With