Angular Template-driven Forms Subcomponent
▌Introduction
▌Environment
▋Angular 2.4.0
▋Angular CLI
1.0.0-beta.31
▌Implement
Consider that we have a Form that will show different
inputs when an option is changed.
Here we will use two components to
display different inputs.
▋Main component
<!--<pre>{{form.value | json}}</pre>-->
<form novalidate #form="ngForm" (ngSubmit)="onSubmit(form)">
<div class="form-horizontal">
<div class="form-group required">
<label class="control-label col-md-2">Product Type</label>
<div class="col-md-3">
<select class="form-control" required name="type" #type="ngModel" ngModel>
<option *ngFor="let pt of productTypes" [ngValue]="pt">{{pt.name}}</option>
</select>
</div>
</div>
<cms-sub-list *ngIf="type.value?.id=='1'" [product]="prod" ></cms-sub-list>
<cms-sub-detail *ngIf="type.value?.id=='2'" [product]="prod"></cms-sub-detail>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-success" [disabled]="form.invalid" />
<input type="button" value="Back" class="btn btn-warning" [routerLink]="['/Cms/Layout/Product/List']" />
</div>
</div>
</div>
</form>
▋Sub component
Here is one of the sub-components.
<div class="form-group required">
<label class="control-label col-md-2">Image</label>
<div class="col-md-3">
<input type="file" name="listPhoto">
</div>
</div>
<div class="form-group required">
<label class="control-label col-md-2">Banner</label>
<div class="col-md-3">
<input type="file" name="ListPhoto">
</div>
</div>
<div class="form-group required">
<label class="control-label col-md-2">Template</label>
<div class="col-md-3">
<input type="radio" value="list" checked="checked" name="template" #template="ngModel" [(ngModel)]="prod.template">
<img src="assets/images/prod_template_1.png" width="300px" align="top" class="preview">
<input type="radio" value="detail" name="template" #template="ngModel" [(ngModel)]="prod.template">
<img src="assets/images/prod_template_2.png" width="300px" align="top" class="preview">
</div>
</div>
<div class="form-group required">
<label class="control-label col-md-2">Name</label>
<div class="col-md-3">
<input type="text" class="form-control" required name="title" #title="ngModel" [(ngModel)]="prod.title" />
</div>
</div>
<div class="form-group required">
<label class="control-label col-md-2">Publish date</label>
<div class="col-md-3">
<input type="text" class="form-control" required name="publishDate" #publishDate="ngModel" [(ngModel)]="prod.publishDate" />
</div>
</div>
<div class="form-group required">
<label class="control-label col-md-2">Remove date</label>
<div class="col-md-3">
<input type="text" class="form-control" required name="downDate" #downDate="ngModel" [(ngModel)]="prod.downDate" />
</div>
</div>
<div class="form-group required">
<label class="control-label col-md-2">Description</label>
<div class="col-md-3">
<textarea required name="description" #description="ngModel" [(ngModel)]="prod.description"></textarea>
</div>
</div>
▋The problem
Now we have a problem that
the form value only contains the parent component’s NgModels but without
subcomponent’s.
The form.value is shown
below.
▋How to solve the problem
We have to add the
subcomponent’s NgModels to the parent component’s NgForm.
▋ Sub-component
import { NgForm, NgModel } from '@angular/forms';
import { Component, OnInit, Input, ViewChildren, QueryList } from '@angular/core';
@Component({
selector: 'cms-sub-list',
templateUrl: './sub-list.component.html'
})
export class SubListComponent implements OnInit {
@ViewChildren(NgModel) controls: QueryList<NgModel>;
@Input('product') prod: Product;
constructor(private parentForm: NgForm) { }
ngOnInit() {
}
ngAfterViewInit() {
this.controls.forEach((control: NgModel) => {
this.parentForm.addControl(control);
});
}
}
u Inject the parent component’s NgForm.
And finally we could get the
correct NgForm in parent component.
沒有留言:
張貼留言