I have an angular 6 app. And I have a form like below stackblitz.
But, I want create a shared country-state
component. And I want to call when I need. So, I convert my project into below stackblitz. But, I don't want create new form group for country-state
. I want to use from parent . But, I can't execute my second stackblitz.
How can I achieve this?
That's a main purpose of @Input()
decorator in angular:
In your country-state.component.ts
add Input
to your import and use that decorator as mentioned below:
import { Component, OnInit, Input } from '@angular/core';
...
@Component({
selector: 'app-country-state',
templateUrl: './country-state.component.html',
styleUrls: ['./country-state.component.css']
})
export class CountryStateComponent implements OnInit {
countries: Country[];
states: State[];
@Input()
studentForm; // <-- This
...
}
Then in your app.component.ts change your child tag to:
<app-country-state [studentForm]="studentForm"></app-country-state>
After that and in your country-state.component.html
add form
tag like :
<form [formGroup]="studentForm">
<label>Country:</label>
<select formControlName="countryId" (change)="onSelect($event.target.value)">
<option [value]="0">--Select--</option>
<option *ngFor="let country of countries" [value]="country.id">{{country.name}}</option>
</select>
<br/><br/>
<label>State:</label>
<select formControlName="stateId">
<option [value]="0">--Select--</option>
<option *ngFor="let state of states " value= {{state.id}}>{{state.name}}</option>
</select>
</form>
Thus, you wont create a new formgroup
instance but you'll be using the parent's one.
Try composite form using controlContainer
parent.component.ts
this.studentForm = new FormGroup({
'studentName': new FormControl(''),
'stateId': new FormControl(''),
'countryId': new FormControl('')
})
parent.component.html
<form [formGroup]="studentForm" (ngSubmit)="onSubmit()">
<label>Student Name:</label>
<input formControlName="studentName">
<br/><br/>
<app-country-state></app-country-state>
<br/><br/>
<button type="submit">SAVE</button>
</form>
Inside child component provide ViewContainer to get parent group control
import { Component, OnInit } from '@angular/core';
import { Country } from '../country';
import { State } from '../state';
import { SelectService } from '../select.service';
import { FormControl, FormGroupDirective, FormGroup, ControlContainer } from '@angular/forms';
@Component({
selector: 'app-country-state',
templateUrl: './country-state.component.html',
styleUrls: ['./country-state.component.css'],
viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }]
})
export class CountryStateComponent implements OnInit {
countryId;
countryState: FormGroup;
countries: Country[];
states: State[];
constructor(private selectService: SelectService, private parentcontrol: FormGroupDirective) { }
ngOnInit() {
this.countryState = this.parentcontrol.control;
this.parentcontrol.control.updateValueAndValidity();
// this.parentcontrol.control.addControl('stateId', new FormControl(''));
this.countries = this.selectService.getCountries();
}
onSelect(countryid) {
// this.states = this.selectService.getStates().filter((item) => item.countryid == this.studentForm.controls.countryId.value);
}
}
you need to pass your formGroup to child component as an input
country-state.component.ts
@Input() studentForm;
in app.component.html
<app-country-state [studentForm]="studentForm"></app-country-state>
in country-state.component.html
<form [formGroup]="studentForm" >
....
</form>
I have modified your code https://stackblitz.com/edit/angular-q3pqgk
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.