[Angular] Content Projection with ng-content
For example there is tow form compoennts on the page, and what we want to do is reusing the form component. Make to tow form behave differently, we can using <ng-content> inside form and pass what we want from the parent component.
// app.component.ts <div> <auth-form (submitted)="createUser($event)"> <h3>Create account</h3> <button type="submit"> Join us </button> </auth-form> <auth-form (submitted)="loginUser($event)"> <h3>Login</h3> <button type="submit"> Login </button> </auth-form> </div>
For each form we have different event handler such as 'createUser' and 'loginUser'. Besides that for each form we pass one h3 tag and one button tag.
To see how it should looks like:
Now let's see how to write form component to make this happen.
// auth-form.component.ts <div> <form (ngSubmit)="onSubmit(form.value)" #form="ngForm"> <ng-content select="h3"></ng-content> <label> Email address <input type="email" name="email" ngModel> </label> <label> Password <input type="password" name="password" ngModel> </label> <ng-content select="button"></ng-content> </form> </div>
<ng-content> has 'select' attr, which is similar to css selector, you can use component, class, id...
The way I prefer is attribute selector:
<auth-form (submitted)="createUser($event)"> <h3 auth-form-title>Create account</h3> <button auth-form-submit type="submit"> Join us </button> </auth-form>
So we you can use it like:
<div> <form (ngSubmit)="onSubmit(form.value)" #form="ngForm"> <ng-content select="[auth-form-title]"></ng-content> <label> Email address <input type="email" name="email" ngModel> </label> <label> Password <input type="password" name="password" ngModel> </label> <ng-content select="[auth-form-submit]"></ng-content> </form> </div>
ng-content also accept customer component.
For example, there is a component:
@Component({ selector: 'auth-remember', template: ` <label> <input type="checkbox" (change)="onChecked($event.target.checked)"> Keep me logged in </label> ` }) export class AuthRememberComponent { @Output() checked: EventEmitter<boolean> = new EventEmitter<boolean>(); onChecked(value: boolean) { this.checked.emit(value); } }
And we can use it:
<auth-form (submitted)="loginUser($event)"> <h3>Login</h3> <auth-remember (checked)="rememberUser($event)"> </auth-remember> <button type="submit"> Login </button> </auth-form>
Insie form component, we add slot for the new component.
<div> <form (ngSubmit)="onSubmit(form.value)" #form="ngForm"> <ng-content select="h3"></ng-content> <label> Email address <input type="email" name="email" ngModel> </label> <label> Password <input type="password" name="password" ngModel> </label> <ng-content select="auth-remember"></ng-content> <ng-content select="button"></ng-content> </form> </div>
Lastly, just like 'switch' in any programming lanugage, it has a 'default' case, for content projection is the same, anything which is not match to the selector, it will goes to default slot. So how to define a default slot for content projection?
Actually it is quite símple:
<div> <ng-content select=".higlight"></ng-content> <ng-content select="authComponent"></ng-content> <!-- Default case--> <ng-content></ng-content> </div>
相关文章
- [Angular Unit Testing] Testing component with content projection
- [Angular Unit Testing] Testing Component with ChangeDetectionStrategy.OnPush
- [ngx-formly] Implement cross-cutting functionality with Angular Formly Extensions
- [Python] Indexing An Array With Another Array with numpy
- [Angular] Create dynamic content with <tempalte>
- [Angular2 Animation] Control Undefined Angular 2 States with void State
- [Angular 2] Share Template Content In Another Template With Content Projection <ng-content>
- [Angular2 Form] Use RxJS Streams with Angular 2 Forms
- [Angular 2] Nesting Elements in Angular 2 Components with ng-content (AKA Angular 2 Transclusion)
- [Angular 2] Inject Service with "Providers"
- [Angular 2] Get start with Firebase
- [Angular 2] Using events and refs
- [Angular Unit Testing] Testing component with content projection
- [Angular] Use Angular components in AngularJS applications with Angular Elements
- [Angular] Modify User Provided UI with Angular Content Directives
- [Angular] Set Metadata in HTTP Headers with Angular HttpHeaders
- [Angular] Handle HTTP Errors in Angular with HttpErrorResponse interface
- [Angular] Bind async requests in your Angular template with the async pipe and the "as" keyword
- [Angular] Dynamic components with ComponentFactoryResolver
- [Angular 2] Share Template Content In Another Template With Content Projection <ng-content>
- [Angular 2] Order Dynamic Components Inside an Angular 2 ViewContainer
- [Angular 2] Nesting Elements in Angular 2 Components with ng-content (AKA Angular 2 Transclusion)
- [Angular 2] Passing data to components with 'properties'
- [Angular 2] Passing data to components with @Input
- SAP UI5和Angular的事件处理机制比较
- Angular HTTP 请求自定义 timeout 值的一种实现思路
- Angular 自定义 structural 指令的一个例子
- Angular async pipe在Component html模板中的一个实际应用