2

I create a angular 6 project where I fetch a nested company object that holds multiple addresses to display in a view. I want to display only two of them per child view and use a pagination to display the rest. I use ngx-pagination and reactive forms.

But unfortunately pagination doesn't work correct. It only displays the first two addresses (if "pageSize" = 2) and nothing changes when I click on the pagination control. Only the value for the "currentPage" (p - in my case) changes.

If I check my company object it is populated with all exiting addresses for this company, but I don't get them displaed.

What am I doing wrong?

If I change the "itmesPerPage" the the number of exiting addresses I can display al of them - that all.

For testing I used "splice pipe", but the effect is the same. I can only display the first addresses and never - for example - the last one.

If I "inspect" my element in the view and click on the controls, the page change is recognised but nothing changes.

This is my "company-detail componet ts" to create the abstract controls and loads the data from the server:

ngOnInit() {

 this.companyDetailForm = this.formBuilder.group({
      id: [null],
      companyName: [''],
      middleName: [''],
      lastName: [''],
      created: [null],
      status: [''],
      isDeleted: [null],
      contactAddresses: this.formBuilder.array([
        this.addContactAddressFormGroup()
      ])
});
//Load the data
this.route.data.subscribe(data => {
  this.company = data['company']; // 'company' = name (..resolve: {company: ...) from route path in routes.ts
  this.companyDetailForm.patchValue({
   id: this.company.id,
   companyName: this.company.companyName,
   middleName: this.company.middleName,
   lastName: this.company.lastName,
   created: this.company.created,
   status: this.company.status,
   isDeleted: this.company.isDeleted,
   contactAddresses: this.company.contactAddresses
  });

  this.companyDetailForm.setControl('contactAddresses',
                                        this.setExistingContactAddresses(this.company.contactAddresses) );

  });

}

// initialize Form
addContactAddressFormGroup(): FormGroup {
return this.formBuilder.group({
  contactId: [null],
  addressId: [null],
  line1: ['Test'],
  line2: ['Test2'],
  line3: ['Test3'],
  city: [''],
  region: [''],
  postalCode: [''],
  country: [''],
  created: [''],
  status: [''],
  isDeleted: [null],
  addressType: [''],
});

}

setExistingContactAddresses(conAddSets: ContactAddress[]): FormArray {
const conAddFormArray = new FormArray([]);
conAddSets.forEach(cas => {
  conAddFormArray.push(this.formBuilder.group({
    line1: cas.line1,
    line2: cas.line2,
    line3: cas.line3,
    postalCode: cas.postalCode,
    city: cas.city,
    region: cas.region,
    country: cas.country
  }));
});
console.log(this.companyDetailForm);
return conAddFormArray;

}

The relevant part of the view, where the magic should happen:

.......

<div class col-sm-8>
        <div class="tab-panel">
            <tabset class="company-tabset">
                <tab heading="Addresses">
                  <div class="card-deck" style="width: auto">
                  <div formArrayName="contactAddresses"  *ngFor="let contactAddress of companyDetailForm['controls']['contactAddresses']['controls'] | paginate: { itemsPerPage: pageSize, currentPage: p } ; let i = index" >
                    <div [formGroupName]="i">
                      <div class="card">
                        <div class="card-header">

                        </div>
                        <div class="card-body" >
                          <div class="card-text">
                              <div class="form-group" aria-autocomplete="none">
                                  <strong><label for="line1">Street</label></strong>
                                  <input class="form-control" type="text" id="line1" formControlName="line1">
                                  <input class="form-control" type="text" id="line2" formControlName="line2">
                                  <input class="form-control" type="text" id="line3" formControlName="line3">
                              </div>
                              <div class="form-group" aria-autocomplete="none">
                                  <strong><label for="postalCode">Zip - City - Region</label></strong>
                                  <input class="form-control" type="text" id="postalCode" formControlName="postalCode">
                                  <input class="form-control" type="text" id="city" formControlName="city">
                                  <input class="form-control" type="text" id="region" formControlName="region">
                              </div>
                              <div class="form-group" aria-autocomplete="none">
                                  <strong><label for="country">Country</label></strong>
                                  <input class="form-control" type="text" id="country" formControlName="country">
                              </div>

                          </div>
                        </div>
                      </div>


                    </div>                                           

                  </div>                  

                  </div>

                  <div class="text-center mt-4">
                    <pagination-controls (pageChange)="p = $event" autoHide="true"></pagination-controls>
                    {{p}}
                  </div>                                           


                </tab>

I am new to angular and any help would be appreciated.

Many thanks in advance Tom

TagNoT
  • 21
  • 5

3 Answers3

2

I had the same issue. Form Control was not updated because formGroupName that is equal to i was always the same on different pages. For page 1, indexes were 1 and 2, for page 2, again 1 and 2. This is because we are looping in the paginated part of formArray. To fix it I created a function that creates an index from the pageSize, currentPage an item index.

The idea is next:

  fieldGlobalIndex(index) {
    return this.pageSize * (this.currentPage - 1) + index;
  }

Then just replace:

 [formGroupName]="i" -> [formGroupName]="fieldGlobalIndex(i)"

Hope this will help.

1

In your html template, when you paginate contactAddresses, you get indexes i as [0,1],[0,1] and so on. But the angular form indexes are still going [0,1,2,3,4...n]. That's probably the problem.

Create a function, that dynamically generates index for instance generateIndex(i), that returns i + pageSize * pageIndex.

António Almeida
  • 9,620
  • 8
  • 59
  • 66
Rihards M
  • 11
  • 3
0

instead of calculating the FormGroup index with the help of current page selected, add a new 'index' formcontrol to the formGroup and then pass that index in FormGroup

Example: *ngFor="let item of abcForm?.get('ABC')?.controls (consider this ngFor with a formArray ABC)

to set the FormGroup use the approach as: formGroupName={{item.value.index}}