我正在尝试使用Angular 7应用程序中的第三方ngx-file-drop组件上传多个文件。
我正在遍历类型为NgxFileDropEntry
的文件对象。该对象只有两个属性,分别为fileEntry
和relativePath
。但是,在遍历对象时,我可以在HTML代码中分配selectedDocumentItem
和selectedDate
。
这些属性在运行时在调试期间在组件中可见,但在编译时抱怨。我使用了上面的方法,以便当用户单击上载按钮时可以保存记录,因为所有值都可以通过该对象获得。
在保存对象之前,我需要使用文件对象中的值填充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);
}
}
}
答案 0 :(得分:1)
TypeScript是JavaScript的superset。
它只是存在一个用于强制类型的 compile-time 层(香草JS中缺少的某种层)。这就是为什么您只会收到编译时错误而不是运行时错误的原因。
看看NgxFileDropEntry
的{{3}},我确实发现它确实只有两个属性,即relativePath
和fileEntry
,所以编译器当然会在您使用时抱怨尝试访问该类型(您添加的属性)上不存在的属性。
我建议做的是创建您自己的自定义类型,以包装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"