在 table angular 中仅从一行中选择文件

Choosing files from only one row in a table angular

我有一个 table,其中有一列包含选择文件的选项。我已经这样做了,但我的问题是,当我在特定行中选择文件时,所有行中的文件都会被选择。即使我删除它也会在所有行中被删除。我希望它只在一行中被选中或删除。

STACKBLITZ

@angular 为 table 循环中的文件删除 ngFor,如下所示。因为它一次又一次地循环相同的文件。

<div>* {{myFiles[i].name}}</div>
<button type="button" (click)="deleteRow(i)" class="btn btn-primary">X</button>

而不是这个

<div *ngFor="let file of myFiles; let i=index">
  <div>* {{myFiles[i].name}}</div>
  <button type="button" (click)="deleteRow(i)" class="btn btn-primary">X</button>
</div>

然后你像下面这样声明包含索引、文件、isUpload 的文件对象

myfiles: {index: string, file: any, isUpload: boolean}[] = [];

请查看 stackblitz 参考 url。

参考:https://stackblitz.com/edit/angular-ivy-jbgfgn?file=src%2Fapp%2Fapp.component.ts

When file in any row is selected, you have following same code in each row:

<div *ngFor="let file of myFiles; let i=index">
  <div>* {{file.name}}</div>
  <button type="button" (click)="deleteRow(i)" class="btn btn-primary">X</button>
</div>

每行打印所有文件。按某些行标识符存储文件(例如 name)。

所以改变

myFiles: any[] = [];

myFiles: Record<string, File[]> = {};

getFileDetails() 函数应该接收 name 键:

getFileDetails (e, name) {
  //console.log (e.target.files);
  for (var i = 0; i < e.target.files.length; i++) { 
    this.myFiles[name] = this.myFiles[name] || [];
    this.myFiles[name].push(e.target.files[i]);
  }
  console.log(this.myFiles)
}

uploadFiles():

uploadFiles() {
  const frmData = new FormData();

  Object.values(this.myFiles).flat().forEach(file => frmData.append("fileUpload", file));
}

deleteRow() 函数应该接收 name 键:

deleteRow(index: number, name: string) {
  this.myFiles[name].splice(index,1);
  // reset file input element
  (document.querySelector(`#file_${name}`) as HTMLInputElement).files = undefined;
}

相关TDHTML:

<td>
  <div>
    <ng-container>
      <input type="file" id="file" multiple
        (change)="getFileDetails($event, list.name)">
    </ng-container>
  </div>

  <div *ngFor="let file of myFiles[list.name]; let i=index">
    <div>* {{file.name}}</div>
    <button type="button" (click)="deleteRow(i, list.name)" class="btn btn-primary">X</button>
  </div>
</td>

请注意,STACKBLITZ 可能尚不支持 Object.values(this.myFiles).flat(),但任何现代浏览器都支持 should work

您可以改用以下内容:

Object.values(this.myFiles).reduce((res, curr) => [
  ...res,
  ...curr
], []).forEach(file => frmData.append("fileUpload", file));

工作STACKBLITZ

这里有一些修改,将维护具有实际记录(行)的文件列表。

首先修改listes数据模型:

{
      name: "A",
      qty: 6,
      value: 10,
      files: [] // added files array here
    },

接下来,修改getFileDetails 代码。您需要索引和目标。然后,按索引找到列表并将 target.files 推到该列表对象(行)上:

  getFileDetails (index, e) {
    //console.log (e.target.files);
    for (var i = 0; i < e.target.files.length; i++) { 
      this.listes[index].files.push(e.target.files[i]);
    }
    console.log(this.myFiles)
  }

更改delete 方法以从所选索引中删除所选文件。在这种情况下,我们需要两个索引,一个用于列表,一个用于文件。这些是在HTML(下)中创建的:

  deleteRow(listIndex: number, fileIndex: number) {
    this.listes[listIndex].files.splice(fileIndex,1);
  }

最后 html 所需的更改很少,但与我上面提到的索引有关:

                <tbody>
                    <tr *ngFor="let list of listes; index as listIndex">
                        <td>{{listIndex+1}}</td>
                        <td>{{list.name}}</td>
                        <td>{{list.qty}}</td>
                        <td>{{list.value}}</td>
                        <div style="overflow: auto;">
                            <td>
                                <div>
                                    <ng-container>
                                        <input type="file"  multiple
            (change)="getFileDetails(listIndex, $event)">
                                    </ng-container>
                                </div>
                                <div *ngFor="let file of list.files; index as fileIndex">
                                    <div>* {{file.name}}</div>
                                    <button type="button" (click)="deleteRow(listIndex, fileIndex)" class="btn btn-primary">X</button>
                                </div>
                            </td>
                        </div>
                    </tr>
                </tbody>

OP询问删除文件后清除文件输入。以下更改实现了这一点:

    <input #fileInput type="file" multiple (change)="getFileDetails(listIndex, $event)">
    </ng-container>
    </div>
    <div *ngFor="let file of list.files; index as fileIndex">
      <div>* {{file.name}}</div>
      <button type="button" (click)="deleteRow(listIndex, fileIndex); fileInput.value = ''" class="btn btn-primary">X</button>

工作闪电战可以在这里找到:https://stackblitz.com/edit/angular-ivy-gepzrz?file=src%2Fapp%2Fapp.component.html