I have tried all methods and checked related stackoverflow questions and nothing worked so asking here. I have to create ui where on select of dropdown an api call is made and data is received in form of an array . Based on this array i want to add as many fields to my form as there are number of elements in array. I tried using FormArray but it did not work. As i keep getting error related to cannot find control with specified name 'name'. I tried using making formcontrol fields dynamic but still getting the same error.
Here is the code that i tried .
.ts file
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl, FormArray } from '@angular/forms';
import { HttpClient } from '@angular/mon/http';
@Component({
selector: 'app-calculator',
templateUrl: './calculatorponent.html',
styleUrls: ['./calculatorponent.scss']
})
export class CalculatorComponent implements OnInit {
title = 'Formula Calculation Page';
configUrlProducts = 'http://localhost:3000/data/products';
configUrlProductFieldsData = 'http://localhost:3000/data/getproductfields/';
angForm: FormGroup;
ruleset_data=[];
ruleset_data_length=0;
products: any = [];
selected_product_id;
syntax_error=false
show_form=false;
arr=[{'name':''},{'class':''},{'tree':''}];
temp;
// products=[{"id":1,"name":'Product 1'},{"id":2,"name":'Product 2'},{"id":3,"name":'Product 3'}]
constructor(private fb: FormBuilder,private http: HttpClient) {
console.log("inside constructor")
// this.createForm();
// this.fetch_products();
}
// convenience getters for easy access to form fields
get f() { return this.angForm.controls; }
get t() { return this.f.fields as FormArray; }
ngOnInit() {
console.log("inside ngonit");
this.angForm = this.fb.group({
fields: new FormArray([])
});
for(var i=0;i<3;i++){
this.temp=this.arr[i];
this.t.push(this.fb.group({'name':''}))
}
// this.arr.forEach(item=>{
// this.t.push(this.fb.group(item))
// })
console.log(this.angForm)
this.getProducts();
}
getProducts() {
console.log("inside get products");
this.products = [];
this.http.get(this.configUrlProducts).subscribe((res)=>{
console.log(res);
this.products = res["data"];
});
}
fetch_ruleset_data(value: string){
this.selected_product_id=value;
console.log("inside get rule data");
this.ruleset_data = [];
this.http.get(this.configUrlProductFieldsData+value).subscribe((res)=>{
console.log(res);
this.ruleset_data = res["data"];
this.show_form=true;
console.log(this.angForm);
this.ruleset_data_length=res["data"].length;
});
}
onSubmit(value){
console.log(value);
// var data=value;
// data["no_of_variables"]=this.ruleset_data_length;
// data["product_id"]=this.selected_product_id;
// // value=value+this.ruleset_data_length;
// // var formula=JSON.parse(value);
// console.log("final data before sending to api",data);
// return this.http.post('http://localhost:3000/formula/addformula', data)
// .subscribe((res)=>{
// console.log(res);
// })
}
validateFormula=(c: FormControl)=> {
console.log(c.value,typeof c.value);
var data={};
data['formula']=c.value;
data["no_of_variables"]=this.ruleset_data_length;
data["product_id"]=this.selected_product_id;
return this.http.post('http://localhost:3000/formula/validateformula', data)
.subscribe((res)=>{
// console.log("inside validation after api call",res)
// console.log(res["error"])
if(res["error"]){
console.log("inside error block",res);
this.syntax_error=true;
// this.angForm.setErrors({ 'invalid': true });
// return true;
return {
validateFormula: {
valid: true
}
}
}else{
this.syntax_error=false;
// this.angForm.setErrors({ 'invalid': false });
// return true;
return {
validateFormula: {
valid: true
}
}
}
})
// let EMAIL_REGEXP;
// return EMAIL_REGEXP.test(c.value) ? null : {
// validateEmail: {
// valid: false
// }
// };
}
// fetch_ruleset_data(value: string){
// console.log(value);
// }
}
.html file
<!-- appponent.html -->
<div class="container">
<h1>
Wele to {{title}}!!
</h1>
<select class="custom-select" (change)="fetch_ruleset_data($event.target.value)">
<option value="" disabled>Choose your product</option>
<option *ngFor="let product of products; let i = index" [value]="product.id">
{{product.name}}
</option>
</select>
<div *ngIf="show_form==true">
<form [formGroup]="angForm" (ngSubmit)="onSubmit(angForm.value)">
<div *ngFor="let item of t.controls; let i = index">
<div [formGroup]="item">
<input [formControlName]='item'>
</div>
</div>
<button type="submit">Submit</button>
</form>
</div>
<br />
</div>
Have been struggling with this from past 2 days any help is greatly appreciated. I am new to angular and currently learning it it might be a simple thing but i am unable to figure it out at present and need your help.
I have tried all methods and checked related stackoverflow questions and nothing worked so asking here. I have to create ui where on select of dropdown an api call is made and data is received in form of an array . Based on this array i want to add as many fields to my form as there are number of elements in array. I tried using FormArray but it did not work. As i keep getting error related to cannot find control with specified name 'name'. I tried using making formcontrol fields dynamic but still getting the same error.
Here is the code that i tried .
.ts file
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl, FormArray } from '@angular/forms';
import { HttpClient } from '@angular/mon/http';
@Component({
selector: 'app-calculator',
templateUrl: './calculator.ponent.html',
styleUrls: ['./calculator.ponent.scss']
})
export class CalculatorComponent implements OnInit {
title = 'Formula Calculation Page';
configUrlProducts = 'http://localhost:3000/data/products';
configUrlProductFieldsData = 'http://localhost:3000/data/getproductfields/';
angForm: FormGroup;
ruleset_data=[];
ruleset_data_length=0;
products: any = [];
selected_product_id;
syntax_error=false
show_form=false;
arr=[{'name':''},{'class':''},{'tree':''}];
temp;
// products=[{"id":1,"name":'Product 1'},{"id":2,"name":'Product 2'},{"id":3,"name":'Product 3'}]
constructor(private fb: FormBuilder,private http: HttpClient) {
console.log("inside constructor")
// this.createForm();
// this.fetch_products();
}
// convenience getters for easy access to form fields
get f() { return this.angForm.controls; }
get t() { return this.f.fields as FormArray; }
ngOnInit() {
console.log("inside ngonit");
this.angForm = this.fb.group({
fields: new FormArray([])
});
for(var i=0;i<3;i++){
this.temp=this.arr[i];
this.t.push(this.fb.group({'name':''}))
}
// this.arr.forEach(item=>{
// this.t.push(this.fb.group(item))
// })
console.log(this.angForm)
this.getProducts();
}
getProducts() {
console.log("inside get products");
this.products = [];
this.http.get(this.configUrlProducts).subscribe((res)=>{
console.log(res);
this.products = res["data"];
});
}
fetch_ruleset_data(value: string){
this.selected_product_id=value;
console.log("inside get rule data");
this.ruleset_data = [];
this.http.get(this.configUrlProductFieldsData+value).subscribe((res)=>{
console.log(res);
this.ruleset_data = res["data"];
this.show_form=true;
console.log(this.angForm);
this.ruleset_data_length=res["data"].length;
});
}
onSubmit(value){
console.log(value);
// var data=value;
// data["no_of_variables"]=this.ruleset_data_length;
// data["product_id"]=this.selected_product_id;
// // value=value+this.ruleset_data_length;
// // var formula=JSON.parse(value);
// console.log("final data before sending to api",data);
// return this.http.post('http://localhost:3000/formula/addformula', data)
// .subscribe((res)=>{
// console.log(res);
// })
}
validateFormula=(c: FormControl)=> {
console.log(c.value,typeof c.value);
var data={};
data['formula']=c.value;
data["no_of_variables"]=this.ruleset_data_length;
data["product_id"]=this.selected_product_id;
return this.http.post('http://localhost:3000/formula/validateformula', data)
.subscribe((res)=>{
// console.log("inside validation after api call",res)
// console.log(res["error"])
if(res["error"]){
console.log("inside error block",res);
this.syntax_error=true;
// this.angForm.setErrors({ 'invalid': true });
// return true;
return {
validateFormula: {
valid: true
}
}
}else{
this.syntax_error=false;
// this.angForm.setErrors({ 'invalid': false });
// return true;
return {
validateFormula: {
valid: true
}
}
}
})
// let EMAIL_REGEXP;
// return EMAIL_REGEXP.test(c.value) ? null : {
// validateEmail: {
// valid: false
// }
// };
}
// fetch_ruleset_data(value: string){
// console.log(value);
// }
}
.html file
<!-- app.ponent.html -->
<div class="container">
<h1>
Wele to {{title}}!!
</h1>
<select class="custom-select" (change)="fetch_ruleset_data($event.target.value)">
<option value="" disabled>Choose your product</option>
<option *ngFor="let product of products; let i = index" [value]="product.id">
{{product.name}}
</option>
</select>
<div *ngIf="show_form==true">
<form [formGroup]="angForm" (ngSubmit)="onSubmit(angForm.value)">
<div *ngFor="let item of t.controls; let i = index">
<div [formGroup]="item">
<input [formControlName]='item'>
</div>
</div>
<button type="submit">Submit</button>
</form>
</div>
<br />
</div>
Have been struggling with this from past 2 days any help is greatly appreciated. I am new to angular and currently learning it it might be a simple thing but i am unable to figure it out at present and need your help.
Share Improve this question edited Dec 12, 2019 at 8:29 georgeawg 49k13 gold badges77 silver badges98 bronze badges asked Dec 12, 2019 at 6:52 user7760120user7760120 1- Hello Please paste your code here stackblitz. and make it work, in this way it'd much easer to help – Lasha Sumbadze Commented Dec 12, 2019 at 7:28
2 Answers
Reset to default 2You can use FormArray
and FormGroup
to get desired result.
An example can be seen at stackblitz.
HTML:
<form [formGroup]="myForm">
<ng-container *ngFor="let group of myForm.controls |keyvalue">
<div [formGroup]="group.value">
<button type="button" (click)="onAddProduct(group.value)">Add Product</button>
<div formArrayName="productList">
<div *ngFor="let item of productArray(group.value).controls; let i = index">
<label for="">Your row</label>
<input [formControlName]="i">
<button (click)="removeProduct(group.value,i)">remove</button>
</div>
</div>
</div>
<pre>
{{myForm?.value|json}}
</pre>
</ng-container>
</form>
TypeScript:
name = 'Angular';
public myForm: FormGroup;
ngOnInit() {
this.myForm = new FormGroup({});
for(let item of ['item1']) {
this.myForm.addControl(item,
new FormGroup({
name: new FormControl(),
productList: new FormArray([])
})
)
}
}
onAddProduct(group:FormGroup) {
(group.get('productList') as FormArray).push(new FormControl())
}
productArray(group:FormGroup):FormArray
{
return group.get('productList') as FormArray;
}
removeProduct(group:FormGroup,index:number)
{
(group.get('productList') as FormArray).removeAt(index)
}
I don't know about the data you receivedImagine the data you received, your example show that is some like
[{'name':''},{'class':''},{'tree':''}];
Really is a terrible data. It's more "natural" received some like
[{col:'name',value:''},{col:'class',value:''},{col:'tree',value:''}];
But i supouse is another question. The "key" is create a FormGroup when received the data and (in your case, create an array with the name of the fields) iterate over the array
this.http.get(this.configUrlProducts).subscribe((res:any[])=>{
this.formGroup=new FormGroup({}) //<--create a formGroup empty
this.fields=[] //<--create an array empty
res.forEach(x=>{
const key=Object.keys(x)[0]
const value=x[key]
this.formGroup.addControl(key,new FormControl(value))
this.fields.push(key)
})
});
So, your .html can be like
<form [formGroup]="formGroup">
<div *ngFor="let col of fields">
<input [formControlName]="col">
</div>
</form>
If the array you received is like "my natural" way, the function and the .html changes like
this.http.get(this.configUrlProducts).subscribe((res:any[])=>{
this.formGroup=new FormGroup({}) //<--create a formGroup empty
res.forEach(x=>{
const key=x.col
const value=x.value
this.formGroup.addControl(key,new FormControl(value))
})
this.fields=res;
});
<form [formGroup]="formGroup">
<div *ngFor="let field of fields">
<input [formControlName]="field.col">
</div>
</form>
This idea can scale if you received an array of object with name, value, validators, label... becaosue you can use,e.g. {{field.label}} to show the label
If you received ['a','b','c'] you can use
this.http.get(this.configUrlProducts).subscribe((res:any[])=>{
this.formGroup=new FormGroup({}) //<--create a formGroup empty
res.forEach(x=>{
this.formGroup.addControl(x,new FormControl(''))
})
this.fields=res;
});
<form [formGroup]="formGroup">
<div *ngFor="let field of fields">
<input [formControlName]="field">
</div>
</form>
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745276575a4620079.html
评论列表(0条)