Lucifer
Lucifer

Reputation: 2347

Angular FormArray Index not getting passed into Input file type change event

I have an Angular ReactiveForms FormArray which basically renders an expansion panel with file input. I want to pass the index of the FormArray's FormGroup against which a file gets selected. For this I am passing the index (bankAccountIndex) as an additional parameter to the file input (change) event. However, the value is always zero. If I hardcode the value in markup, then I get that value in code-behind, but not when I pass the index variable.

Below is my code:

 <mat-accordion [togglePosition]="'before'">
              <ng-container *ngFor="let bankFormGroup of bankAccountsFormArray.controls; let bankAccountIndex=index">
                <ng-container [formGroupName]="bankAccountIndex">
                  <mat-expansion-panel>
                    <span>
                       <label for="file-upload" class="override-margin-bottom" [ngClass]="{'disabled-control': form.disabled}">
                           <fa-icon [icon]="faUpload" class="file-upload-icon" size="lg"></fa-icon>
                       </label>
                       <input type="file" id="file-upload" (change)="onHandleBankLogoUploadEvent($event.target.files, bankAccountIndex)"
                                style="display: none;" />
                       <input type="text" #bankLogo formControlName="bankLogoBase64Image" style="display: none;">
                       <img [src]="bankLogo.value" *ngIf="bankLogo.value" style="height: 30px;" />
                    </span>
                </mat-expansion-panel>
           </ng-container>
      </ng-container>
 </mat-accordion>

The TypeScript File Input Change event handler:

onHandleBankLogoUploadEvent(files: FileList, bankAccountIndex: number) {
    ...
}

My components OnInit():

ngOnInit() {
    this.toastrService.overlayContainer = this.toastContainer;
    this.toastrService.clear();

    this.initializeForm();

    this.bankAccounts$ = this.firestore.collection<BankAccount>('bankAccounts')
      .valueChanges({ idField: 'docId' })
      .pipe(tap(result => {
        this.bankAccounts = result;
        this.distinctBankNames = result.map(bank => bank.bankName).filter((value, index, self) => self.indexOf(value) === index);
      }));

    this.bankAccounts$_subscription = this.bankAccounts$.subscribe(_ => {
      this.userContext$_subscription = this.appStoreService.userContext$.subscribe(context => {
        if (!!context) {
          this.toastrService.clear();
          this.selectedUser = context;
          this.selectedUserDocId = this.selectedUser.docId;
          this.initializeForm();
        } else {
          this.toastrService.info('Please select a specific family member.', null,
            {
              closeButton: true,
              disableTimeOut: true,
              enableHtml: false,
              positionClass: 'toast-top-center',
              easeTime: 100
            });
        }
      });
    });
  }

  initializeForm() {
    this.userFormGroup = this.formBuilder.group({
      isActive: [true, Validators.required],
      firstName: [this.selectedUser ? this.selectedUser.firstName : '', Validators.required],
      lastName: [this.selectedUser ? this.selectedUser.lastName : '', Validators.required],
      gender: [this.selectedUser ? this.selectedUser.gender : null, Validators.required],
      email: [this.selectedUser ? this.selectedUser.email : ''],
      pan: [this.selectedUser ? this.selectedUser.pan : ''],
      mobile: [this.selectedUser ? this.selectedUser.mobile : ''],
      aadharId: [this.selectedUser ? this.selectedUser.aadharId : ''],
      bankAccounts: this.selectedUser && this.selectedUser.bankAccountsRefs && this.selectedUser.bankAccountsRefs.length > 0 ?
        this.buildBankAccountsFormArray(this.selectedUser.bankAccountsRefs) : this.formBuilder.array([]),
      passports: this.selectedUser && this.selectedUser.passports && this.selectedUser.passports.length > 0 ?
        this.buildPassportsFormArray(this.selectedUser.passports) : this.formBuilder.array([]),
      webLogins: this.selectedUser && this.selectedUser.webLogins && this.selectedUser.webLogins.length > 0 ?
        this.buildWebLoginsFormArray(this.selectedUser.webLogins) : this.formBuilder.array([]),
    });
  }

  buildBankAccountsFormArray(bankAccountsRefs: DocumentReference[]): FormArray {
    if (bankAccountsRefs && bankAccountsRefs.length > 0) {
      const usersBankAccounts = this.bankAccounts.filter(acct => bankAccountsRefs.some(ref => ref.path.includes(acct.docId)));

      const bankAccountFormGroups = usersBankAccounts.map(acct => this.formBuilder.group({
        docId: [acct.docId],
        bankName: [acct.bankName, Validators.required],
        bankLogoBase64Image: [acct.bankLogoBase64Image],
        accountNumber: [acct.accountNumber, Validators.required],
        ifscCode: [acct.ifscCode, Validators.required],
        loginUserId: [acct.loginUserId],
        loginPassword: [acct.loginPassword],
        transactionPassword: [acct.transactionPassword],
        isActive: [acct.isActive, Validators.required],
      }))
      return this.formBuilder.array(bankAccountFormGroups);
    }
  }

Upvotes: 1

Views: 804

Answers (1)

Maciej Kasprzak
Maciej Kasprzak

Reputation: 949

Your problem are the ids. You should assign unique id to the each of the inputs:

<label [for]="'file-upload-' + bankAccountIndex" class="override-margin-bottom" [ngClass]="{'disabled-control': form.disabled}">
   <fa-icon [icon]="faUpload" class="file-upload-icon" size="lg"></fa-icon>
</label>
<input type="file" [id]="'file-upload-' + bankAccountIndex" (change)="onHandleBankLogoUploadEvent($event.target.files, bankAccountIndex)" style="display: none;" />

Upvotes: 5

Related Questions