1

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);
    }
  }
9
  • Are there any errors in the console? Can you show your .ts file? Commented Dec 30, 2020 at 9:59
  • No, there are no errors. As I said, I get a value, but it's always zero. Commented Dec 30, 2020 at 10:01
  • Please show your .ts file. HTML looks correct, but there might be something wrong with typescript. Commented Dec 30, 2020 at 10:08
  • Well, it's a 700 lines file...what part of the file are you interested in ? Commented Dec 30, 2020 at 10:11
  • Let's start with initialization of bankAccountsFormArray. And btw. your ngFor works correct (besides the index)? You get more than one element rendered? Commented Dec 30, 2020 at 10:12

1 Answer 1

5

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;" />
Sign up to request clarification or add additional context in comments.

1 Comment

Awesome...worked perfectly...thanks you so much. Really appreciate you help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.