I am trying to convert a html form to a nested json. These are my classes :
export class Config {
id: string;
name: string;
email: string;
lchart:ComponentLinechart;
}
export class ComponentLinechart {
name_linechart : String;
xAxis_linechart : String;
yAxis_linechart : String;
}
The formcomponent.ts:-
export class FormsComponent implements OnInit {
newConfig: Config = new Config();
constructor(private service : MyserviceService, private configservice:ConfigurationService) {
}
email = new FormControl('', [Validators.required, Validators.email]);
xAxisControl = new FormControl('', Validators.required);
yAxisControl = new FormControl('', Validators.required);
name_linechart = new FormControl('', Validators.required);
name = new FormControl('', Validators.required);
getConfig(): void {
this.configservice.getConfig()
.subscribe(data => this.configs = data );
}
createConfiguration(todoForm: NgForm): void {
this.configservice.createConfig(this.newConfig)
.subscribe(createconfig => {
todoForm.reset();
this.newConfig = new Config();
this.configs.unshift(createconfig)
});
}
The formcomponent.html :-
<form #todoForm="ngForm" (ngSubmit)="createConfiguration(todoForm)" novalidate>
<div class="example-container">
<mat-form-field appearance="fill">
<mat-label>Enter your name</mat-label>
<input matInput [(ngModel)]="newConfig.name" name="name" [formControl]="name" required>
</mat-form-field>
<br>
<mat-form-field appearance="fill">
<mat-label>Enter your email</mat-label>
<input matInput placeholder="pat@example.com" [(ngModel)]="newConfig.email" name="email"
[formControl]="email" required>
<mat-error *ngIf="email.invalid">{{getErrorMessage()}}</mat-error>
</mat-form-field>
<br>
<mat-form-field appearance="fill">
<mat-label>Name-linechart</mat-label>
<input matInput [(ngModel)]="newConfig.name_linechart" name="name_linechart"
[formControl]="name_linechart" required>
</mat-form-field>
<br>
<mat-form-field *ngIf = "sales" >
<mat-label>xAxis-linechart</mat-label>
<mat-select [(ngModel)]="newConfig.xAxis-linechart" name="xAxis-linechart"
[formControl]="xAxisControl" required>
<mat-option *ngFor="let field of fields" [value] = "field">
{{field}}
</mat-option>
</mat-select>
<mat-error *ngIf="xAxisControl.hasError('required')">Please choose a field</mat-error>
</mat-form-field>
<br>
<mat-form-field *ngIf = "sales" >
<mat-label>yAxis-linechart</mat-label>
<mat-select [(ngModel)]="newConfig.yAxis-linechart" name="yAxis-linechart"
[formControl]="yAxisControl" required>
<mat-option *ngFor="let field of fields" [value] = "field">
{{field}}
</mat-option>
</mat-select>
<mat-error *ngIf="yAxisControl.hasError('required')">Please choose a field</mat-error>
</mat-form-field>
Expected result :
{
"name": "adam",
"email": "adam@gmail.com",
"lchart": {
"name_linechart": "books",
"xAxis_linechart": "library",
"yAxis_linechart": "percentage"
}
}
But this is what I get :
{
"name": "adam",
"email": "adam@gmail.com",
"lchart": null
}
I tried to write newConfig.lchart.name_linechart in the formcomponent.html but it gives me the error :
TypeError : cannot read property name_linechart of undefined.
Foufa, NEVER, NEVER, NEVER, NEVER use [(ngModel)] and formControlName (or formControl) in the same tag. One is for template Form, another for ReactiveForms, see the docs
Well. You has an object that has properties, one of them is an object, so, you has a FormGroup with somes FormControls and one FormGroup, (again the docs)
myForm=new FormGroup({
name:new FormControl(),
email:new FormControl(),
lchart:new FormGroup({
name_linechart: new FormControl(),
xAxis_linechart: new FormControl(),
yAxis_linechart: new FormControl(),
})
})
And the .html
<form [formGroup]="myForm">
<!--see, under the formGroup, we using formControlName for the formControl-->
<input formControlName="name">
<input formControlName="email">
<!--when we has a FomgGroup, we use formGrpupName in a div-->
<div formGroupName="lchart">
<!--and formControlName under the div -->
<input formControlName="name_linechart">
<input formControlName="xAxis_linechart">
<input formControlName="yAxis_linechart">
</div>
</form>
<!--we can add, only for check-->
<pre>
{{myForm?.value|json}}
</pre>
Update as always, is util use a function that received an object and create the form
getForm(data:any)
{
data=data || { name:null,
email:null,
lchart:{
name_linechart:null,
xAxis_linechart:null,
yAxis_linechart:0
}
}
return new FormGroup({
name:new FormControl(data.name,Validator.required),
email:new FormControl(data.email,[Validator.required,Validators.emailValidator),
lchart:new FormGroup({
name_linechart: new FormControl(data.lchart.name_linechart),
xAxis_linechart: new FormControl(data.lchart.xAxis_linechart),
yAxis_linechart: new FormControl(data.lchart.yAxis_linechart),
})
}
And use as
myForm=this.getForm(data) //<--if we has an object "data"
//or
myForm=this.getForm(null) //if we want a empty form