【问题标题】:Angular FormArray Index not getting passed into Input file type change eventAngular FormArray 索引未传递到输入文件类型更改事件
【发布时间】:2021-04-06 20:12:29
【问题描述】:

我有一个 Angular ReactiveForms FormArray,它基本上呈现一个带有文件输入的扩展面板。我想传递 FormArray 的 FormGroup 的索引,根据该索引选择文件。为此,我将索引 (bankAccountIndex) 作为附加参数传递给文件输入(更改)事件。但是,该值始终为零。如果我在标记中对值进行硬编码,那么我会在代码隐藏中获得该值,但在传递索引变量时不会。

下面是我的代码:

 <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>

TypeScript 文件输入更改事件处理程序:

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

我的组件 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);
    }
  }

【问题讨论】:

  • 控制台有错误吗?你能展示你的 .ts 文件吗?
  • 不,没有错误。正如我所说,我得到一个值,但它始终为零。
  • 请出示您的 .ts 文件。 HTML 看起来是正确的,但 typescript 可能有问题。
  • 嗯,这是一个 700 行的文件……你对文件的哪一部分感兴趣?
  • 让我们从bankAccountsFormArray 的初始化开始。顺便说一句。您的 ngFor 工作正常(除了索引)?您渲染了多个元素?

标签: angular angular-reactive-forms


【解决方案1】:

你的问题是 ids。 您应该为每个输入分配唯一的 ID:

<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;" />

【讨论】:

  • 太棒了...工作得很好...非常感谢。非常感谢您的帮助。
猜你喜欢
  • 2018-07-17
  • 2020-03-31
  • 1970-01-01
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 2020-04-18
  • 2018-09-24
  • 1970-01-01
相关资源
最近更新 更多