@coreteq/ngx-projection v0.3.0
👻 Flexible way to project dynamic content
✨ Ngx-projection library provides NgxContentOutlet standalone structural directive, that allows you to project dynamic content as well as:
- *ngTemplateOutlet, that creates embedded views based on the TemplateRef template
- *ngComponentOutlet, that creates a dynamic component based on a reference to the component class
- or a simple {{ interpolation }} that displays a primitive value tied to a variable in the template
Compatibility with Angular Versions
Table of contents
🚀 Installation
npm install @coreteq/ngx-projection
Setup
Add standalone directive NgxContentOutlet
to app NgModule
import { NgxContentOutlet } from '@coreteq/ngx-projection';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, NgxContentOutlet], // <--- you need to add NgxContentOutlet
bootstrap: [AppComponent]
})
export class AppModule {}
Usage
Use with component class reference
Getting as input a reference to the component class, the *ngxContentOutlet
directive dynamically instantiates the component and inserts its host view into this container.
<ng-container *ngxContentOutlet="component as content">
{{ content }}
</ng-container>
<!--- or --->
<ng-container *ngxContentOutlet="component"></ng-container>
import { ChildComponent } from './child.component'
export class AppComponent {
component = ChildComponent;
}
Use with optional custom injector
Optional custom injector that will be used as parent for the component. Defaults to the injector of the current view container.
<ng-container *ngxContentOutlet="component as content; injector: customInjector">
{{ content }}
</ng-container>
import { ChildComponent } from './child.component';
import { Injector } from "@angular/core";
export class RendererComponent {
component = ChildComponent;
customInjector: Injector;
constructor(injector: Injector) {
this.customInjector = Injector.create({
parent: injector,
providers: [
{
provide: SOME_TOKEN,
useValue: 'Some value',
},
],
});
}
}
import { Inject } from "@angular/core";
import { SOME_TOKEN } from './tokens';
export class ChildComponent {
constructor(@Inject(SOME_TOKEN) token: string) {}
}
Use with TemplateRef
In this case *ngxContentOutlet
inserts an embedded view from a prepared TemplateRef
<ng-container *ngxContentOutlet="templateRef"></ng-container>
<ng-template #templateRef>
<div>
<p> Well, that's where we met! </p>
</div>
</ng-template>
Use with a context object
Also, you can attach a context object to the EmbeddedViewRef
by context
option.
<ng-container *ngxContentOutlet="templateRef; context: context"></ng-container>
<ng-template #templateRef let-name let-message="message">
<div>
<p> {{name}}, {{message}} </p>
</div>
</ng-template>
NOTE: Using the key
$implicit
in the context object will set its value as default. Read moreexport class AppComponent { readonly context = { $implicit: 'Houston', message: 'we have a problem' }; }
Use with optional custom injector
You can pass a custom injector to be used within the embedded view.
ParentComponent
<!--- ParentComponent provides his own injector to the content --->
<ng-container *ngxContentOutlet="content as implicit; injector: parentInjector">
{{ implicit }}
</ng-container>
import { inject, Input } from "@angular/core";
import { ReflectiveContent } from "@coreteq/ngx-projection";
export class ParentComponent {
@Input()
content: ReflectiveContent<any>;
parentInjector = inject(Injector);
}
NOTE: See ReflectiveContent type
AppComponent
<app-parent [content]="templateRef"></app-parent>
<ng-template #templateRef>
#### ChildComponent
```ts
import { ParentComponent } from "./parent.component";
import { Inject } from "@angular/core";
export class ChildComponent {
constructor(@Inject(ParentComponent) parent: ParentComponent) {}
}
Use with primitive type value
And finally *ngxContentOutlet
directive allows to use interpolation to display the primitive value. Thanks to as
keyword, you can assign to another variable result of ngxContentOutlet.
<ng-container *ngxContentOutlet="value as content">
{{ content }}
</ng-container>
export class AppComponent {
// primitive 'string'
// also *ngxContentOutlet accepts 'number', 'undefined' and 'null'
value = 'A Cold Day in Hell';
}
API
Input | Type | Default | Required | Description |
---|---|---|---|---|
[ngxContentOutlet] | ReflectiveContent<T> | n/a | yes | |
[ngxContentOutletContext] | Record<string, unknown> | n/a | no | |
[ngxContentOutletInjector] | Injector | n/a | no | |
[ngxContentOutletContent] | any[][] | n/a | no |
ReflectiveContent
is a union type:
export type ReflectiveContent<T> = | Type<T> | TemplateRef<Partial<T>> | string | number | null | undefined;