mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
docs: enhance programmatic rendering guide by covering ngComponentOutlet options
(cherry picked from commit f9e9fc4ffe)
This commit is contained in:
@@ -41,6 +41,159 @@ export class CustomDialog {
|
||||
}
|
||||
```
|
||||
|
||||
### Passing inputs to dynamically rendered components
|
||||
|
||||
You can pass inputs to the dynamically rendered component using the `ngComponentOutletInputs` property. This property accepts an object where keys are input names and values are the input values.
|
||||
|
||||
```angular-ts
|
||||
@Component({
|
||||
selector: 'user-greeting',
|
||||
template: `
|
||||
<div>
|
||||
<p>User: {{ username() }}</p>
|
||||
<p>Role: {{ role() }}</p>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class UserGreeting {
|
||||
username = input.required<string>();
|
||||
role = input('guest');
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'profile-view',
|
||||
imports: [NgComponentOutlet],
|
||||
template: `
|
||||
<ng-container
|
||||
*ngComponentOutlet="greetingComponent; inputs: greetingInputs()"
|
||||
/>
|
||||
`
|
||||
})
|
||||
export class ProfileView {
|
||||
greetingComponent = UserGreeting;
|
||||
greetingInputs = signal({ username: 'ngAwesome' , role: 'admin' });
|
||||
}
|
||||
```
|
||||
|
||||
The inputs are updated whenever the `greetingInputs` signal changes, keeping the dynamic component in sync with the parent's state.
|
||||
|
||||
### Providing content projection
|
||||
|
||||
Use `ngComponentOutletContent` to pass projected content to the dynamically rendered component. This is useful when the dynamic component uses `<ng-content>` to display content.
|
||||
|
||||
```angular-ts
|
||||
@Component({
|
||||
selector: 'card-wrapper',
|
||||
template: `
|
||||
<div class="card">
|
||||
<ng-content />
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class CardWrapper { }
|
||||
|
||||
@Component({
|
||||
imports: [NgComponentOutlet],
|
||||
template: `
|
||||
<ng-container
|
||||
*ngComponentOutlet="cardComponent; content: cardContent()"
|
||||
/>
|
||||
|
||||
<ng-template #contentTemplate>
|
||||
<h3>Dynamic Content</h3>
|
||||
<p>This content is projected into the card.</p>
|
||||
</ng-template>
|
||||
`
|
||||
})
|
||||
export class DynamicCard {
|
||||
private vcr = inject(ViewContainerRef);
|
||||
cardComponent = CardWrapper;
|
||||
|
||||
private contentTemplate = viewChild<TemplateRef<unknown>>('contentTemplate');
|
||||
|
||||
cardContent = computed(() => {
|
||||
const template = this.contentTemplate();
|
||||
if (!template) return [];
|
||||
// Returns an array of projection slots. Each element represents one <ng-content> slot.
|
||||
// CardWrapper has one <ng-content>, so we return an array with one element.
|
||||
return [this.vcr.createEmbeddedView(template).rootNodes];
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Providing injectors
|
||||
|
||||
You can provide a custom injector to the dynamically created component using `ngComponentOutletInjector`. This is useful for providing component-specific services or configuration.
|
||||
|
||||
```angular-ts
|
||||
export const THEME_DATA = new InjectionToken<string>('THEME_DATA', {
|
||||
factory: () => 'light',
|
||||
});
|
||||
|
||||
@Component({
|
||||
selector: 'themed-panel',
|
||||
template: `<div [class]="theme">...</div>`
|
||||
})
|
||||
export class ThemedPanel {
|
||||
theme = inject(THEME_DATA);
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'dynamic-panel',
|
||||
imports: [NgComponentOutlet],
|
||||
template: `
|
||||
<ng-container
|
||||
*ngComponentOutlet="panelComponent; injector: customInjector"
|
||||
/>
|
||||
`
|
||||
})
|
||||
export class DynamicPanel {
|
||||
panelComponent = ThemedPanel;
|
||||
|
||||
customInjector = Injector.create({
|
||||
providers: [
|
||||
{ provide: THEME_DATA, useValue: 'dark' }
|
||||
],
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Accessing the component instance
|
||||
|
||||
You can access the dynamically created component's instance using the directive's `exportAs` feature:
|
||||
|
||||
```angular-ts
|
||||
@Component({
|
||||
selector: 'counter',
|
||||
template: `<p>Count: {{count()}}</p>`
|
||||
})
|
||||
export class Counter {
|
||||
count = signal(0);
|
||||
increment() {
|
||||
this.count.update(c => c + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
imports: [NgComponentOutlet],
|
||||
template: `
|
||||
<ng-container
|
||||
*ngComponentOutlet="counterComponent"
|
||||
#outlet="ngComponentOutlet"
|
||||
/>
|
||||
|
||||
<button (click)="outlet.componentInstance?.increment()">
|
||||
Increment
|
||||
</button>
|
||||
`
|
||||
})
|
||||
export class CounterHost {
|
||||
counterComponent = Counter;
|
||||
}
|
||||
```
|
||||
|
||||
NOTE: The `componentInstance` property is `null` before the component is rendered.
|
||||
|
||||
See the [NgComponentOutlet API reference](api/common/NgComponentOutlet) for more information on the
|
||||
directive's capabilities.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user