在Angular 7中填充在对象上迭代的数组

时间:2019-07-04 11:31:15

标签: angular typescript

我正在尝试使用Angular 7应用程序中的第三方ngx-file-drop组件上传多个文件。

我正在遍历类型为NgxFileDropEntry的文件对象。该对象只有两个属性,分别为fileEntryrelativePath。但是,在遍历对象时,我可以在HTML代码中分配selectedDocumentItemselectedDate

这些属性在运行时在调试期间在组件中可见,但在编译时抱怨。我使用了上面的方法,以便当用户单击上载按钮时可以保存记录,因为所有值都可以通过该对象获得。

在保存对象之前,我需要使用文件对象中的值填充uploadDocument对象,以将其传递给服务。

我无法填充uploadDocument对象。我的逻辑有任何问题。我正在使用for循环吗?

<div class="upload-table">
    <table id="table1" class="center">

        <tbody class="upload-name-style">
            <tr *ngFor="let item of files; let i=index">
                <td> <input kendoTextBox [(ngModel)]="item.relativePath" style="width: 350px" /></td>
                <td>
                    <kendo-dropdownlist style="width:350px" [(ngModel)]="item.selectedDocumentItem" 
                        [data]="DocumentTypes" [defaultItem]="defaultItem" [filterable]="false" textField="Name"
                        valueField="Id">
                    </kendo-dropdownlist>
                </td>
                <td>
                    <kendo-datepicker style="width: 200px" [format]="'dd MMM, yyyy'"
                        [(ngModel)]="item.selectedDate"></kendo-datepicker>
                </td>
                <td> <button class="btn btn-default" (click)="deleteRow(i)"><i class="fa fa-trash"></i>Delete
                    </button></td>
            </tr>
        </tbody>
    </table>


</div>

JSON

[{"relativePath":"Simplex - Copy - Copy.xlsx","fileEntry":{"name":"Simplex - Copy - Copy.xlsx","isDirectory":false,"isFile":true},"selectedDocumentItem":{"Id":6,"Name":"Constitutional Documents"},"selectedDate":"2019-07-09T23:00:00.000Z"},{"relativePath":"Simplex - Copy (2).xlsx","fileEntry":{"name":"Simplex - Copy (2).xlsx","isDirectory":false,"isFile":true},"selectedDocumentItem":{"Id":10,"Name":"Manager Letters"},"selectedDate":"2019-07-13T23:00:00.000Z"},{"relativePath":"Simplex - Copy.xlsx","fileEntry":{"name":"Simplex - Copy.xlsx","isDirectory":false,"isFile":true},"selectedDocumentItem":{"Id":7,"Name":"Regulation / References"},"selectedDate":"2019-07-30T23:00:00.000Z"}]

组件

document: IDocument ;
uploadDocument: IDocument[] = [];
public files: NgxFileDropEntry[] = [];

  public createDocument() {
    console.log(this.files);

  this.files.forEach(element => {

        this.uploadDocument.forEach(doc => {

            doc.id = 5508,
            doc.documentTypeId = element.selectedDocumentItem.Id ,
            doc.name = element.relativePath,
            doc.documentDate = element.selectedDate

          });


    });

根据达伦的建议尝试的解决方案

html

 <div class="upload-table">
        <table id="table1" class="center">



            <tbody class="upload-name-style">
                <tr *ngFor="let item of documents; let i=index">
                    <td> <input kendoTextBox [(ngModel)]="item.fileDropEntry.relativePath" style="width: 350px" /></td>
                    <td>
                        <kendo-dropdownlist style="width:350px" [(ngModel)]="item.documentTypeId" 
                            [data]="DocumentTypes" [defaultItem]="defaultItem" [filterable]="false" textField="Name"
                            valueField="Id">
                        </kendo-dropdownlist>
                    </td>
                    <td>
                        <kendo-datepicker style="width: 200px" [format]="'dd MMM, yyyy'"
                            [(ngModel)]="item.documentDate"></kendo-datepicker>
                    </td>
                    <td> <button class="btn btn-default" (click)="deleteRow(i)"><i class="fa fa-trash"></i>Delete
                        </button></td>
                </tr>
            </tbody>
        </table>


    </div>

组件

    export interface IDocumentUpload {
        fileDropEntry: NgxFileDropEntry;
        id: number;
        name: string;
        documentTypeId: number;
        documentDate: Date;
    }

 documents : IDocumentUpload[] = [];

     public createDocument() {
            console.log(this.documents);
     }


 public dropped(files: NgxFileDropEntry[]) {
    this.files = files;
    for (const droppedFile of files) {

        // Is it a file?
        if (droppedFile.fileEntry.isFile) {
            const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
            fileEntry.file((file: File) => {

                // Here you can access the real file
                console.log(droppedFile.relativePath, file);
                console.log('Hello');

                /**
                // You could upload it like this:
                const formData = new FormData()
                formData.append('logo', file, relativePath)

                // Headers
                const headers = new HttpHeaders({
                  'security-token': 'mytoken'
                })

                this.http.post('https://mybackend.com/api/upload/sanitize-and-save-logo', formData, { headers: headers, responseType: 'blob' })
                .subscribe(data => {
                  // Sanitized logo returned from backend
                })
                **/

            });
        } else {
            // It was a directory (empty directories are added, otherwise only files)
            const fileEntry = droppedFile.fileEntry as FileSystemDirectoryEntry;
            console.log(droppedFile.relativePath, fileEntry);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

TypeScript是JavaScript的superset

它只是存在一个用于强制类型的 compile-time 层(香草JS中缺少的某种层)。这就是为什么您只会收到编译时错误而不是运行时错误的原因。

看看NgxFileDropEntry的{​​{3}},我确实发现它确实只有两个属性,即relativePathfileEntry,所以编译器当然会在您使用时抱怨尝试访问该类型(您添加的属性)上不存在的属性。

我建议做的是创建您自己的自定义类型,以包装NgxFileDropEntry,其中也包含您的自定义属性。像这样:

export interface SomeCustomNameThatMakeseSense {
  fileDropEntry: NgxFileDropEntry;
  documentItem: WhateverTheTypeOfThisIs;
  date: Date;
}

然后,无论从何处获取files,您都可以简单地实例化一个SomeCustomNameThatMakeseSense的新对象,并在HTML中使用它来向其中添加属性。

编辑:

似乎有些混乱,所以我想通过添加更多解释来澄清这些问题:

我建议您做的是(从上方)创建类型SomeCustomNameThatMakeseSense new 对象,包装您的files数组。您不想将现有对象强制转换为这种新类型,因为这只会隐藏问题。

更改:

public files: NgxFileDropEntry[] = [];

收件人:

public files: SomeCustomNameThatMakeseSense[] = [];

更改:

public dropped(files: NgxFileDropEntry[]) {
  this.files = files;
 // Other code removed for the sake brevity 
}

收件人:

public dropped(files: NgxFileDropEntry[]) {
  this.files = files.map(file => ({
    fileDropEntry: file,
    documentItem: undefined, // Give this a default value of your own choice
    date: new Date() // Same here as above
  }));
  // Other code removed for the sake brevity 
}

然后在您的HTML更改中

*ngFor="let item of documents; let i=index"

收件人:

*ngFor="let item of files; let i=index"