7

I have a Json data like this:

assets/details.json

{
    "name" : "john",
    "age"  : 20,
    "address" : [{
        "main": "address1",
        "sub": "address2"
    },
    {
        "main": "add1",
        "sub": "add2"
    }]
}

I want to show those all JSON data in Angular forms with patchValue.

I've tried this.

app.component.ts

export class AppComponent {
  data: FormGroup

  constructor(private FB: FormBuilder, private service: DataService) { }

  ngOnInit() {
    this.data = this.FB.group({
      name: [''],
      age: [''],
      address: this.FB.array([
        this.addAddress()
      ])
    })

    this.getData()

  }

  addAddress(): FormGroup {
    return this.FB.group({
      main: [''],
      sub: [''],
    })
  }

  getData() {
    this.service.getData('../assets/details.json').subscribe((data) => {
      this.data.patchValue({ data })
    }
}

And I've design my HTML page like this: app.component.html

<form [formGroup]="data" (ngSubmit)="onSubmit()">
  <input formControlName="name" type="text" class="form-control col-sm-8">
  <input formControlName="age" type="number" class="form-control col-sm-8">

  <div formArrayName="address" *ngFor="let d of data.get('address').controls; let i = index;">
    <div [formGroupName]="i">
      <input formControlName="main" type="text" class="form-control">
      <input formControlName="sub" type="text" class="form-control" />
    </div>
  </div>
</form>

But nothing works as I expected. Nothing can fill up to the form. I don't know how to do further.

How can I get all those JSON data in form fields?

7
  • you need to invoke the patchValue() method on the formControl not the formGroup Commented Jan 29, 2019 at 17:31
  • I could't get that. Can you explain more ? Commented Jan 29, 2019 at 17:32
  • If not, than How can do that in formGroup ? I'm new to angular. Commented Jan 29, 2019 at 17:33
  • Does it work with this.data.patchValue(data) instead of this.data.patchValue({data}) ? Commented Jan 29, 2019 at 17:42
  • try patching the control e.g. this.data.controls.name.patchValue(data.name); and then the same for the rest Commented Jan 29, 2019 at 17:46

4 Answers 4

10

patchValue only updates the existing FormArray, it won't modify the structure of your FormArray. You have to make sure your FormArray is of the right size before patching it, you can also recreate it completely, as shown below:

this.data.patchValue({ name: data.name, age: data.age });

this.data.controls['address'] = this.FB.array(data.map(address => {
    const group = this.addAddress();
    group.patchValue(address);
    return group ;
}));

See this post for more details.

Sign up to request clarification or add additional context in comments.

Comments

2

If you were not to have a FormArray in your form, you could just use this.data.patchValue(data) (or setValue if all properties match), but since you have a formarray, you need to iterate your address array in your object and push formgroups to your formarray. Also I see no need to initially create an empty formgroup when building the form, so I have left it out:

ngOnInit() {
  this.data = this.FB.group({
    name: [''],
    age: [''],
    address: this.FB.array([])
  })
}

get formArr() {
  return this.data.get('address') as FormArray;
}

// ....
this.data.patchValue({name: data.name, age: data.age});
data.address.forEach((x) => {
  this.formArr.push(this.FB.group(x))
});

6 Comments

Okay i'll try It.
There's a getter, from where we return the address FormArray. I like to shorten it, so for example in template no need to use let x of data.get('address).controls, you can just use formArr.controls instead, same goes for ts file, but no need for a getter if you don't want one :)
It worked as properly. Thank you for that. But I've a simple problem, it shows an error like that. Could you help me to figure this out, How to solve that ? image link: imgur.com/a/wPQj2Ij
Make sure to clear your FormArray first, as you are only pushing new items when patching
HttpClient parses your response to an object, but doesn't know what that object contains. I assuuuume here you have not typed your response in your service, which causes the issue. Anyway, there's a section in the httpclient documentation. In short, either use bracket notation or make an interface (interface is my suggestion): angular.io/guide/http#type-checking-the-response
|
0
  this.formCustomer.patchValue({ ...response.data })
   response.data.contactos.forEach(c => {
     this.contactos.push(this.Contact(c))
    });
      
get contactos(): FormArray {
  return <FormArray>this.formCustomer.get("contactos")
      }

Contact(item?:any): FormGroup {
        return this.fb.group({
          tipo: [item?item.tipo:'', [Validators.required]],
          nombre: [item?item.nombre:'', [Validators.required]],
          tel: [item?item.tel:'', [Validators.required]],
          tel_2: [item?item.tel_2:''],
        })
      }
this.formCustomer = this.fb.group({
    contactos: this.fb.array([this.Contact()]),
    })

Comments

-1

The getData() method will work like below:

getData() {
    this.service.getData('../assets/details.json').subscribe((_data) => {
      this.data.patchValue(data)
      (this.data as FormGroup).setControl('address', this.fb.array(this.data.address || []);
    }
}

1 Comment

While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.