我正在开发一个 Angular Web 应用程序,它通过 Nebular Stepper 组件收集数据。其中一个步骤允许用户使用包含 type="file" 输入的另一个组件附加图像或文档。附加图像按预期工作,但如果取消文件选择器,底层步进器对话框也会关闭并且数据会丢失。我是否正确地假设这是由关闭文件选择器时触发取消事件引起的?有没有办法阻止该事件到达对话框?
目前,如果我附加通用附件然后将其删除,取消文件选择器不会关闭步进器组件。
我想阻止这种行为,但不确定如何实现。我尝试停止事件传播,但所有尝试都失败了。
stepper.component.ts
/**
* Handler for the selectedFilesChanged event of mat-file-upload component
* for Attachments.
* @param {FileList} fileList List of File objects of the loaded files.
*/
onSelectedAttachmentsChanged(fileList: FileList): void {
// White list for attachments - just PDF for now.
if (fileList.item(0).type == "application/pdf") {
getBase64EncodedFromFile(fileList.item(0)).subscribe({
next: (result: string) => {
const newAttachment: Attachment = {
filename: fileList.item(0).name,
fileExtension: FileExtension.pdf,
data: result,
mimeType: fileList.item(0).type,
};
this.changeRequest.attachments = [
...this.changeRequest.attachments,
newAttachment,
];
},
error: (err: Error) => {
console.log("An error has occurred: ", err);
},
});
} else {
this._dialogService.open(ConfirmDialogComponent, {
context: {
confirmHeader: "Unsupported File Type",
confirmMessage: "Only PDFs can be attached here.",
confirmBtnText: "Ok",
confirmBtnStatus: "basic",
confirmStatus: "info",
confirmShowCancelBtn: false,
},
});
}
}
stepper.component.html
<div fxLayout="row" fxLayoutAlign="center center" fxLayoutGap="1em">
<mat-file-upload
[acceptedTypes]="'.pdf'"
[labelText]="''"
[selectButtonText]="'Attach a PDF'"
[showUploadButton]="false"
[allowMultipleFiles]="false"
(selectedFilesChanged)="onSelectedAttachmentsChanged($event)"
></mat-file-upload>
</div>
mat-file-upload.component.ts
import {
Component,
ElementRef,
EventEmitter,
Input,
Output,
ViewChild,
} from "@angular/core";
@Component({
selector: "mat-file-upload",
template: `
<!--<span class="file-input-text">{{ labelText }}</span>-->
<button
nbButton
[type]="selectFilesButtonType"
[disabled]="disabled"
color="primary"
class="file-input-button"
(click)="fileInput.click()"
[attr.aria-label]="selectButtonText"
>
<nb-icon icon="plus-outline"></nb-icon>
<span>{{ selectButtonText }}</span>
<input
#fileInput
type="file"
style="display: none"
[accept]="acceptedTypes"
[multiple]="allowMultipleFiles"
(change)="filesChanged($event.target.files)"
/>
</button>
<button
mat-raised-button
[type]="uploadButtonType"
color="primary"
class="file-input-button"
[disabled]="!selectedFiles || disabled"
(click)="uploadFiles()"
*ngIf="showUploadButton"
[attr.aria-label]="uploadButtonText"
>
{{ uploadButtonText }}
</button>
<!--<span class="file-input-text">{{ selectedFileText }}</span>-->
<!--<button
mat-icon-button
(click)="filesChanged(null)"
type="button"
aria-label="Remove Selected File(s)"
*ngIf="selectedFiles != null && selectedFiles.length > 0"
>
<mat-icon *ngIf="!customSvgIcon">close</mat-icon>
<mat-icon *ngIf="customSvgIcon" [svgIcon]="customSvgIcon"></mat-icon>
</button>-->
`,
styles: [
".file-input-button { margin-right: 8px !important }",
// eslint-disable-next-line max-len
".file-input-text { font-size: 14px !important; margin-right: 8px !important }",
],
})
export class MatFileUploadComponent {
@Input() labelText = "Select File(s)";
@Input() selectButtonText = "Select File(s)";
@Input() selectFilesButtonType: "button" | "menu" | "reset" | "submit" =
"button";
@Input() uploadButtonText = "Upload File(s)";
@Input() uploadButtonType: "button" | "menu" | "reset" | "submit" = "button";
@Input() allowMultipleFiles = false;
@Input() showUploadButton = true;
@Input() acceptedTypes = "*.*";
@Input() customSvgIcon?: string = null;
@Input() disabled = false;
@Output() uploadClicked: EventEmitter<FileList> = new EventEmitter<
FileList
>();
@Output() selectedFilesChanged: EventEmitter<FileList> = new EventEmitter<
FileList
>();
@ViewChild("fileInput") fileInputRef: ElementRef;
selectedFiles: FileList;
selectedFileText = "";
filesChanged(files?: FileList): void {
this.selectedFiles = files;
this.selectedFilesChanged.emit(this.selectedFiles);
if (this.selectedFiles) {
const numSelectedFiles = this.selectedFiles.length;
this.selectedFileText =
numSelectedFiles === 1
? this.selectedFiles[0].name
: `${numSelectedFiles} files selected`;
} else {
this.selectedFileText = "";
this.resetFileInput();
}
}
uploadFiles(): void {
this.uploadClicked.emit(this.selectedFiles);
this.resetFileInput();
}
resetFileInput(): void {
this.fileInputRef.nativeElement.value = "";
}
}
我确认文件输入正在发出一个取消事件,该事件通过向其构造函数添加事件侦听器来到达我的步进器组件。有没有办法让步进器忽略该事件?
我终于能够通过使用 @HostListener 侦听取消事件并停止其在我的上传组件上的传播来解决我的问题。
@HostListener('cancel', ['$event'])
onCancel(event: Event){
console.log('Cancel host listener.');
event.stopImmediatePropagation();
};