Skip to content
This repository was archived by the owner on Mar 20, 2024. It is now read-only.

Commit df2ff04

Browse files
David Shevitzmhevery
authored andcommitted
docs: initial commit of content projection topic. (#41143)
Content projection is an important part of Angular. However, it has never been documented in the Angular documentation set. This topic attempts to provide the basics of content projection for developers. It is not a comprehensive guide; rather, it is a starting point that we can hopefully expand upon in the future. PR Close #41143
1 parent c9f5b07 commit df2ff04

File tree

17 files changed

+370
-0
lines changed

17 files changed

+370
-0
lines changed

.pullapprove.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ groups:
335335
'aio/content/guide/component-styles.md',
336336
'aio/content/guide/view-encapsulation.md',
337337
'aio/content/examples/component-styles/**',
338+
'aio/content/examples/content-projection/**',
339+
'aio/content/guide/content-projection.md',
338340
'aio/content/guide/dependency-injection.md',
339341
'aio/content/examples/dependency-injection/**',
340342
'aio/content/images/guide/dependency-injection/**',
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { browser, element, by } from 'protractor';
2+
3+
describe('Component Overview', () => {
4+
5+
beforeAll(() => browser.get(''));
6+
7+
it('should display Angular and Content Projection ', async () => {
8+
expect(await element(by.css('h2')).getText()).toEqual('Angular and Content Projection');
9+
});
10+
11+
});

aio/content/examples/content-projection/example-config.json

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
p {
2+
font-family: Lato;
3+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<h2>Angular and Content Projection</h2>
2+
3+
<!-- #docregion single-slot -->
4+
<app-zippy-basic>
5+
<p>Is content projection cool?</p>
6+
</app-zippy-basic>
7+
<!-- #enddocregion single-slot -->
8+
9+
<hr />
10+
11+
<!-- #docregion multi-slot -->
12+
<app-zippy-multislot>
13+
<p question>
14+
Is content projection cool?
15+
</p>
16+
<p>Let's learn about content projection!</p>
17+
</app-zippy-multislot>
18+
<!-- #enddocregion multi-slot -->
19+
20+
<hr />
21+
22+
<h2>Here's a zippy</h2>
23+
24+
<app-example-zippy>
25+
<button appExampleZippyToggle>Is content project cool?</button>
26+
<!-- #docregion ng-template-->
27+
<ng-template appExampleZippyContent>
28+
It depends on what you do with it.
29+
</ng-template>
30+
<!-- #enddocregion ng-template -->
31+
</app-example-zippy>
32+
33+
<hr />
34+
<app-zippy-ngprojectas>
35+
<p>Let's learn about content projection!</p>
36+
<!-- #docregion ngprojectas-->
37+
<ng-container ngProjectAs="question">
38+
<p>Is content projection cool?</p>
39+
</ng-container>
40+
<!-- #enddocregion-->
41+
</app-zippy-ngprojectas>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Component, Directive, Input, TemplateRef, ContentChild, HostBinding, HostListener } from '@angular/core';
2+
3+
@Component({
4+
selector: 'app-root',
5+
templateUrl: './app.component.html'
6+
})
7+
export class AppComponent {}
8+
9+
@Directive({
10+
selector: 'button[appExampleZippyToggle]',
11+
})
12+
export class ZippyToggleDirective {
13+
@HostBinding('attr.aria-expanded') ariaExpanded = this.zippy.expanded;
14+
@HostBinding('attr.aria-controls') ariaControls = this.zippy.contentId;
15+
@HostListener('click') toggleZippy() {
16+
this.zippy.expanded = !this.zippy.expanded;
17+
}
18+
constructor(public zippy: ZippyComponent) {}
19+
}
20+
21+
// #docregion zippycontentdirective
22+
@Directive({
23+
selector: '[appExampleZippyContent]'
24+
})
25+
export class ZippyContentDirective {
26+
constructor(public templateRef: TemplateRef<unknown>) {}
27+
}
28+
// #enddocregion zippycontentdirective
29+
30+
let nextId = 0;
31+
32+
@Component({
33+
selector: 'app-example-zippy',
34+
templateUrl: 'example-zippy.template.html',
35+
})
36+
export class ZippyComponent {
37+
contentId = `zippy-${nextId++}`;
38+
@Input() expanded = false;
39+
// #docregion contentchild
40+
@ContentChild(ZippyContentDirective) content: ZippyContentDirective;
41+
// #enddocregion contentchild
42+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { NgModule } from '@angular/core';
2+
import { BrowserModule } from '@angular/platform-browser';
3+
import { FormsModule } from '@angular/forms';
4+
5+
import {
6+
AppComponent,
7+
ZippyComponent,
8+
ZippyContentDirective,
9+
ZippyToggleDirective,
10+
} from './app.component';
11+
import { ZippyBasicComponent } from './zippy-basic/zippy-basic.component';
12+
import { ZippyMultislotComponent } from './zippy-multislot/zippy-multislot.component';
13+
import { ZippyNgprojectasComponent } from './zippy-ngprojectas/zippy-ngprojectas.component';
14+
15+
@NgModule({
16+
imports: [BrowserModule, FormsModule],
17+
declarations: [
18+
AppComponent,
19+
ZippyComponent,
20+
ZippyToggleDirective,
21+
ZippyContentDirective,
22+
ZippyBasicComponent,
23+
ZippyMultislotComponent,
24+
ZippyNgprojectasComponent,
25+
],
26+
bootstrap: [AppComponent]
27+
})
28+
export class AppModule {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<ng-content></ng-content>
2+
<!-- #docregion ngif -->
3+
<div *ngIf="expanded" [id]="contentId">
4+
<!-- #docregion ng-container -->
5+
<ng-container [ngTemplateOutlet]="content.templateRef"> </ng-container>
6+
<!-- #enddocregion ng-container-->
7+
</div>
8+
<!-- #enddocregion ngif -->
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Component } from '@angular/core';
2+
3+
@Component({
4+
selector: 'app-zippy-basic',
5+
template: `
6+
<h2>Single-slot content projection</h2>
7+
<ng-content></ng-content>
8+
`
9+
})
10+
export class ZippyBasicComponent {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Component } from '@angular/core';
2+
3+
@Component({
4+
selector: 'app-zippy-multislot',
5+
template: `
6+
<h2>Multi-slot content projection</h2>
7+
<ng-content></ng-content>
8+
<ng-content select="[question]"></ng-content>
9+
`
10+
})
11+
export class ZippyMultislotComponent {}

0 commit comments

Comments
 (0)