Eddy Freeman
Eddy Freeman

Reputation: 3309

Issues patching FormArrays values with data from server in Angular

I have an Angular form where a user fills in the form and selects multiple books via checkboxes and send the data to the server. The user can later edit the form again. When a user wants to edit the form, the form must be shown to the user pre-filled with the previous data the user has already submitted.

The problem I am having now is how to pre-filled the checkboxes with the values the user has already submitted. There are five checkboxes and the user can select two. When he wants to edit the data later, i want to pre-select the checkboxes he has selected before.

Current problem

When I run my code, the checkboxes appears and vanishes instantly within a second. Because of that am not able to see whether they are checked or not.

The following is a stripdown of my code so that you can understand the problem.

// Model Interface

export interface BooksModel {
  books?: Array<any>;
}


export class AdviesHandicapComponent implements OnInit {
   private sub: any;
   service: DataService;
   books = new FormArray([]);
   booksModel: BooksModel;
   booksForm: FormGroup;

 booksOptions = [
   {id: 1, book: 'Biology'},
    {id: 2, book: 'Physics'},
    {id: 3, book: 'Chemistry'},
    {id: 4, book: 'Maths'},
    {id: 6, book: 'None of the above'}
  ];

   constructor(private fb: FormBuilder){}

    ngOnInit(): void {
       this.service = new DataService();

       this.sub = this.route.queryParams.subscribe(params => {
       const tok = params['tok'];
       if (tok) {
         const results = this.service.getBooks();
         booksModel = results.reg;
         patchBooksForm();
       }
    });

   const booksFormControls = this.booksOptions.map(book => new FormControl(false));
    this.books = new FormArray(booksFormControls);
    this.booksForm = this.fb.group({
      books: this.books,
    });
   }

   patchBooks(ind: string[]) {
    for (let i = 0; i < this.books.controls.length; i++) {
      for (const d of ind) {
        if (this.booksOptions[i].book === d) {
          this.books.controls[i].patchValue(true);
        }
      }
    }
  }

patchBooksForm(): void {
    patchBooks(this.booksModel.books); // I call this method here to patch the formarray values
    this.booksForm.patchValue({
    books: this.books.controls
    });
  }

}

Data from server

The user may have selected the following books. So when he comes back later I want these books to be selected before he starts editing the form.**

export class DataService {
     getBooks() {
       return  {"reg":{"books":["Biology","Maths"]}};
        }
}

Upvotes: 1

Views: 74

Answers (1)

AVJT82
AVJT82

Reputation: 73367

Based on your code, your untouched form looks like:

{
  "books": [
    false,
    false,
    false,
    false,
    false
  ]
}

To achieve the same when patching, you are now having issues, that you are patching it twice, first time with correct values in your for loop in patchBooks(), second time patching it with the books controls in patchBooksForm(). You should remove those lines:

// remove
// this.booksForm.patchValue({
//   books: this.books.controls
// });

STACKBLITZ

Just a remark, does it make sense to not having any identifier in the formarray, now there's just a bunch of falses and trues, but that is of course up to you :) Also another remark, not related, you should inject your service in the constructor, and not call: this.service = new DataService();.

Upvotes: 1

Related Questions