UNPKG

primeng

Version:

PrimeNG is a premium UI library for Angular featuring a rich set of 90+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeBlock,

1,053 lines (1,049 loc) 87.4 kB
export * from 'primeng/types/fileupload'; import { NgTemplateOutlet, isPlatformBrowser } from '@angular/common'; import { HttpClient, HttpEventType } from '@angular/common/http'; import * as i0 from '@angular/core'; import { InjectionToken, Injectable, inject, output, input, ChangeDetectionStrategy, Component, booleanAttribute, numberAttribute, contentChild, computed, viewChild, signal, effect, ViewEncapsulation, NgModule } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; import { addClass, removeClass } from '@primeuix/utils'; import { TranslationKeys, SharedModule } from 'primeng/api'; import { BaseComponent, PARENT_INSTANCE } from 'primeng/basecomponent'; import * as i1 from 'primeng/bind'; import { Bind } from 'primeng/bind'; import { ButtonDirective } from 'primeng/button'; import { Plus } from '@primeicons/angular/plus'; import { Times } from '@primeicons/angular/times'; import { Upload } from '@primeicons/angular/upload'; import { Message } from 'primeng/message'; import { ProgressBar } from 'primeng/progressbar'; import { Badge } from 'primeng/badge'; import { style } from '@primeuix/styles/fileupload'; import { BaseStyle } from 'primeng/base'; const FILEUPLOAD_INSTANCE = new InjectionToken('FILEUPLOAD_INSTANCE'); const classes = { root: ({ instance }) => `p-fileupload p-fileupload-${instance.mode()} p-component`, header: 'p-fileupload-header', pcChooseButton: 'p-fileupload-choose-button', pcUploadButton: 'p-fileupload-upload-button', pcCancelButton: 'p-fileupload-cancel-button', content: 'p-fileupload-content', fileList: 'p-fileupload-file-list', file: 'p-fileupload-file', fileThumbnail: 'p-fileupload-file-thumbnail', fileInfo: 'p-fileupload-file-info', fileName: 'p-fileupload-file-name', fileSize: 'p-fileupload-file-size', pcFileBadge: 'p-fileupload-file-badge', fileActions: 'p-fileupload-file-actions', pcFileRemoveButton: 'p-fileupload-file-remove-button', basicContent: 'p-fileupload-basic-content' }; class FileUploadStyle extends BaseStyle { name = 'fileupload'; style = style; classes = classes; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FileUploadStyle, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FileUploadStyle }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FileUploadStyle, decorators: [{ type: Injectable }] }); /** * * FileUpload is an advanced uploader with dragdrop support, multi file uploads, auto uploading, progress tracking and validations. * * [Live Demo](https://www.primeng.org/fileupload/) * * @module fileuploadstyle * */ var FileUploadClasses; (function (FileUploadClasses) { /** * Class name of the root element */ FileUploadClasses["root"] = "p-fileupload"; /** * Class name of the header element */ FileUploadClasses["header"] = "p-fileupload-header"; /** * Class name of the choose button element */ FileUploadClasses["pcChooseButton"] = "p-fileupload-choose-button"; /** * Class name of the upload button element */ FileUploadClasses["pcUploadButton"] = "p-fileupload-upload-button"; /** * Class name of the cancel button element */ FileUploadClasses["pcCancelButton"] = "p-fileupload-cancel-button"; /** * Class name of the content element */ FileUploadClasses["content"] = "p-fileupload-content"; /** * Class name of the file list element */ FileUploadClasses["fileList"] = "p-fileupload-file-list"; /** * Class name of the file element */ FileUploadClasses["file"] = "p-fileupload-file"; /** * Class name of the file thumbnail element */ FileUploadClasses["fileThumbnail"] = "p-fileupload-file-thumbnail"; /** * Class name of the file info element */ FileUploadClasses["fileInfo"] = "p-fileupload-file-info"; /** * Class name of the file name element */ FileUploadClasses["fileName"] = "p-fileupload-file-name"; /** * Class name of the file size element */ FileUploadClasses["fileSize"] = "p-fileupload-file-size"; /** * Class name of the file badge element */ FileUploadClasses["pcFileBadge"] = "p-fileupload-file-badge"; /** * Class name of the file actions element */ FileUploadClasses["fileActions"] = "p-fileupload-file-actions"; /** * Class name of the file remove button element */ FileUploadClasses["pcFileRemoveButton"] = "p-fileupload-file-remove-button"; /** * Class name of the content in basic mode */ FileUploadClasses["basicContent"] = "p-fileupload-basic-content"; })(FileUploadClasses || (FileUploadClasses = {})); class FileContent extends BaseComponent { _componentStyle = inject(FileUploadStyle); $pcFileUpload = inject(FILEUPLOAD_INSTANCE); onRemove = output(); files = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "files" }] : /* istanbul ignore next */ [])); badgeSeverity = input('warn', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "badgeSeverity" }] : /* istanbul ignore next */ [])); badgeValue = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "badgeValue" }] : /* istanbul ignore next */ [])); previewWidth = input(50, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "previewWidth" }] : /* istanbul ignore next */ [])); fileRemoveIconTemplate = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "fileRemoveIconTemplate" }] : /* istanbul ignore next */ [])); onRemoveClick(event, index) { this.onRemove.emit({ event, index }); } getRemoveIconContext(iconClass, file, index) { return { class: iconClass, file, index }; } formatSize(bytes) { const k = 1024; const dm = 3; const sizes = this.translate(TranslationKeys.FILE_SIZE_TYPES); if (bytes === 0) { return `0 ${sizes[0]}`; } const i = Math.floor(Math.log(bytes) / Math.log(k)); const formattedSize = (bytes / Math.pow(k, i)).toFixed(dm); return `${formattedSize} ${sizes[i]}`; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FileContent, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: FileContent, isStandalone: true, selector: "[pFileContent]", inputs: { files: { classPropertyName: "files", publicName: "files", isSignal: true, isRequired: false, transformFunction: null }, badgeSeverity: { classPropertyName: "badgeSeverity", publicName: "badgeSeverity", isSignal: true, isRequired: false, transformFunction: null }, badgeValue: { classPropertyName: "badgeValue", publicName: "badgeValue", isSignal: true, isRequired: false, transformFunction: null }, previewWidth: { classPropertyName: "previewWidth", publicName: "previewWidth", isSignal: true, isRequired: false, transformFunction: null }, fileRemoveIconTemplate: { classPropertyName: "fileRemoveIconTemplate", publicName: "fileRemoveIconTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onRemove: "onRemove" }, providers: [FileUploadStyle], usesInheritance: true, ngImport: i0, template: `@for (file of files(); track file?.name + '-' + $index; let index = $index) { <div [class]="cx('file')" [pBind]="$pcFileUpload.ptm('file')"> <img role="presentation" [class]="cx('fileThumbnail')" [attr.alt]="file.name" [src]="file.objectURL" [width]="previewWidth()" [pBind]="$pcFileUpload.ptm('fileThumbnail')" /> <div [class]="cx('fileInfo')" [pBind]="$pcFileUpload.ptm('fileInfo')"> <div [class]="cx('fileName')" [pBind]="$pcFileUpload.ptm('fileName')">{{ file.name }}</div> <span [class]="cx('fileSize')" [pBind]="$pcFileUpload.ptm('fileSize')">{{ formatSize(file.size) }}</span> </div> <p-badge [value]="badgeValue()" [severity]="badgeSeverity()" [class]="cx('pcFileBadge')" [pt]="$pcFileUpload.ptm('pcFileBadge')" [unstyled]="unstyled()" /> <div [class]="cx('fileActions')" [pBind]="$pcFileUpload.ptm('fileActions')"> <button type="button" iconOnly pButton text rounded severity="danger" [class]="cx('pcFileRemoveButton')" [pButtonPT]="$pcFileUpload.ptm('pcFileRemoveButton')" [pButtonUnstyled]="unstyled()" (click)="onRemoveClick($event, index)"> @if (fileRemoveIconTemplate()) { <ng-template *ngTemplateOutlet="fileRemoveIconTemplate(); context: getRemoveIconContext('', file, index)"></ng-template> } @else { <svg data-p-icon="times" [attr.aria-hidden]="true" /> } </button> </div> </div> }`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Badge, selector: "p-badge", inputs: ["badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "directive", type: ButtonDirective, selector: "[pButton]", inputs: ["pButton", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "link", "rounded", "fluid", "variant", "iconOnly", "loading", "severity"] }, { kind: "component", type: Times, selector: "svg[data-p-icon=\"times\"]" }, { kind: "directive", type: Bind, selector: "[pBind]", inputs: ["pBind"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FileContent, decorators: [{ type: Component, args: [{ selector: '[pFileContent]', standalone: true, template: `@for (file of files(); track file?.name + '-' + $index; let index = $index) { <div [class]="cx('file')" [pBind]="$pcFileUpload.ptm('file')"> <img role="presentation" [class]="cx('fileThumbnail')" [attr.alt]="file.name" [src]="file.objectURL" [width]="previewWidth()" [pBind]="$pcFileUpload.ptm('fileThumbnail')" /> <div [class]="cx('fileInfo')" [pBind]="$pcFileUpload.ptm('fileInfo')"> <div [class]="cx('fileName')" [pBind]="$pcFileUpload.ptm('fileName')">{{ file.name }}</div> <span [class]="cx('fileSize')" [pBind]="$pcFileUpload.ptm('fileSize')">{{ formatSize(file.size) }}</span> </div> <p-badge [value]="badgeValue()" [severity]="badgeSeverity()" [class]="cx('pcFileBadge')" [pt]="$pcFileUpload.ptm('pcFileBadge')" [unstyled]="unstyled()" /> <div [class]="cx('fileActions')" [pBind]="$pcFileUpload.ptm('fileActions')"> <button type="button" iconOnly pButton text rounded severity="danger" [class]="cx('pcFileRemoveButton')" [pButtonPT]="$pcFileUpload.ptm('pcFileRemoveButton')" [pButtonUnstyled]="unstyled()" (click)="onRemoveClick($event, index)"> @if (fileRemoveIconTemplate()) { <ng-template *ngTemplateOutlet="fileRemoveIconTemplate(); context: getRemoveIconContext('', file, index)"></ng-template> } @else { <svg data-p-icon="times" [attr.aria-hidden]="true" /> } </button> </div> </div> }`, changeDetection: ChangeDetectionStrategy.OnPush, providers: [FileUploadStyle], imports: [NgTemplateOutlet, Badge, ButtonDirective, Times, Bind] }] }], propDecorators: { onRemove: [{ type: i0.Output, args: ["onRemove"] }], files: [{ type: i0.Input, args: [{ isSignal: true, alias: "files", required: false }] }], badgeSeverity: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeSeverity", required: false }] }], badgeValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeValue", required: false }] }], previewWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewWidth", required: false }] }], fileRemoveIconTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileRemoveIconTemplate", required: false }] }] } }); /** * FileUpload is an advanced uploader with dragdrop support, multi file uploads, auto uploading, progress tracking and validations. * @group Components */ class FileUpload extends BaseComponent { componentName = 'FileUpload'; bindDirectiveInstance = inject(Bind, { self: true }); onAfterViewChecked() { this.bindDirectiveInstance.setAttrs(this.ptm('host')); } /** * Name of the request parameter to identify the files at backend. * @group Props */ name = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "name" }] : /* istanbul ignore next */ [])); /** * Remote url to upload the files. * @group Props */ url = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "url" }] : /* istanbul ignore next */ [])); /** * HTTP method to send the files to the url such as "post" and "put". * @group Props */ method = input('post', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "method" }] : /* istanbul ignore next */ [])); /** * Used to select multiple files at once from file dialog. * @group Props */ multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Comma-separated list of pattern to restrict the allowed file types. Can be any combination of either the MIME types (such as "image/*") or the file extensions (such as ".jpg"). * @group Props */ accept = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "accept" }] : /* istanbul ignore next */ [])); /** * Disables the upload functionality. * @group Props */ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * When enabled, upload begins automatically after selection is completed. * @group Props */ auto = input(false, { ...(ngDevMode ? { debugName: "auto" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates. * @group Props */ withCredentials = input(false, { ...(ngDevMode ? { debugName: "withCredentials" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Maximum file size allowed in bytes. * @group Props */ maxFileSize = input(undefined, { ...(ngDevMode ? { debugName: "maxFileSize" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * Summary message of the invalid file size. * @group Props */ invalidFileSizeMessageSummary = input('{0}: Invalid file size, ', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "invalidFileSizeMessageSummary" }] : /* istanbul ignore next */ [])); /** * Detail message of the invalid file size. * @group Props */ invalidFileSizeMessageDetail = input('maximum upload size is {0}.', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "invalidFileSizeMessageDetail" }] : /* istanbul ignore next */ [])); /** * Summary message of the invalid file type. * @group Props */ invalidFileTypeMessageSummary = input('{0}: Invalid file type, ', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "invalidFileTypeMessageSummary" }] : /* istanbul ignore next */ [])); /** * Detail message of the invalid file type. * @group Props */ invalidFileTypeMessageDetail = input('allowed file types: {0}.', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "invalidFileTypeMessageDetail" }] : /* istanbul ignore next */ [])); /** * Detail message of the invalid file type. * @group Props */ invalidFileLimitMessageDetail = input('limit is {0} at most.', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "invalidFileLimitMessageDetail" }] : /* istanbul ignore next */ [])); /** * Summary message of the invalid file type. * @group Props */ invalidFileLimitMessageSummary = input('Maximum number of files exceeded, ', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "invalidFileLimitMessageSummary" }] : /* istanbul ignore next */ [])); /** * Inline style of the element. * @group Props */ style = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "style" }] : /* istanbul ignore next */ [])); /** * Class of the element. * @group Props */ styleClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "styleClass" }] : /* istanbul ignore next */ [])); /** * Width of the image thumbnail in pixels. * @group Props */ previewWidth = input(50, { ...(ngDevMode ? { debugName: "previewWidth" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * Label of the choose button. Defaults to PrimeNG Locale configuration. * @group Props */ chooseLabel = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "chooseLabel" }] : /* istanbul ignore next */ [])); /** * Label of the upload button. Defaults to PrimeNG Locale configuration. * @group Props */ uploadLabel = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "uploadLabel" }] : /* istanbul ignore next */ [])); /** * Label of the cancel button. Defaults to PrimeNG Locale configuration. * @group Props */ cancelLabel = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "cancelLabel" }] : /* istanbul ignore next */ [])); /** * Icon of the choose button. * @group Props */ chooseIcon = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "chooseIcon" }] : /* istanbul ignore next */ [])); /** * Icon of the upload button. * @group Props */ uploadIcon = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "uploadIcon" }] : /* istanbul ignore next */ [])); /** * Icon of the cancel button. * @group Props */ cancelIcon = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "cancelIcon" }] : /* istanbul ignore next */ [])); /** * Whether to show the upload button. * @group Props */ showUploadButton = input(true, { ...(ngDevMode ? { debugName: "showUploadButton" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Whether to show the cancel button. * @group Props */ showCancelButton = input(true, { ...(ngDevMode ? { debugName: "showCancelButton" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Defines the UI of the component. * @group Props */ mode = input('advanced', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ [])); /** * HttpHeaders class represents the header configuration options for an HTTP request. * @group Props */ headers = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "headers" }] : /* istanbul ignore next */ [])); /** * Whether to use the default upload or a manual implementation defined in uploadHandler callback. Defaults to PrimeNG Locale configuration. * @group Props */ customUpload = input(false, { ...(ngDevMode ? { debugName: "customUpload" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Maximum number of files that can be uploaded. * @group Props */ fileLimit = input(undefined, { ...(ngDevMode ? { debugName: "fileLimit" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * Style class of the upload button. * @group Props */ uploadStyleClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "uploadStyleClass" }] : /* istanbul ignore next */ [])); /** * Style class of the cancel button. * @group Props */ cancelStyleClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "cancelStyleClass" }] : /* istanbul ignore next */ [])); /** * Style class of the remove button. * @group Props */ removeStyleClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "removeStyleClass" }] : /* istanbul ignore next */ [])); /** * Style class of the choose button. * @group Props */ chooseStyleClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "chooseStyleClass" }] : /* istanbul ignore next */ [])); /** * Configuration object forwarded to the choose button. * @group Props */ chooseButtonProps = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "chooseButtonProps" }] : /* istanbul ignore next */ [])); /** * Configuration object forwarded to the upload button. * @group Props */ uploadButtonProps = input({ severity: 'secondary' }, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "uploadButtonProps" }] : /* istanbul ignore next */ [])); /** * Configuration object forwarded to the cancel button. * @group Props */ cancelButtonProps = input({ severity: 'secondary' }, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "cancelButtonProps" }] : /* istanbul ignore next */ [])); /** * Callback to invoke before file upload is initialized. * @param {FileBeforeUploadEvent} event - Custom upload event. * @group Emits */ onBeforeUpload = output(); /** * An event indicating that the request was sent to the server. Useful when a request may be retried multiple times, to distinguish between retries on the final event stream. * @param {FileSendEvent} event - Custom send event. * @group Emits */ onSend = output(); /** * Callback to invoke when file upload is complete. * @param {FileUploadEvent} event - Custom upload event. * @group Emits */ onUpload = output(); /** * Callback to invoke if file upload fails. * @param {FileUploadErrorEvent} event - Custom error event. * @group Emits */ onError = output(); /** * Callback to invoke when files in queue are removed without uploading using clear all button. * @param {Event} event - Browser event. * @group Emits */ onClear = output(); /** * Callback to invoke when a file is removed without uploading using clear button of a file. * @param {FileRemoveEvent} event - Remove event. * @group Emits */ onRemove = output(); /** * Callback to invoke when files are selected. * @param {FileSelectEvent} event - Select event. * @group Emits */ onSelect = output(); /** * Callback to invoke when files are being uploaded. * @param {FileProgressEvent} event - Progress event. * @group Emits */ onProgress = output(); /** * Callback to invoke in custom upload mode to upload the files manually. * @param {FileUploadHandlerEvent} event - Upload handler event. * @group Emits */ uploadHandler = output(); /** * This event is triggered if an error occurs while loading an image file. * @param {Event} event - Browser event. * @group Emits */ onImageError = output(); /** * This event is triggered if an error occurs while loading an image file. * @param {RemoveUploadedFileEvent} event - Remove event. * @group Emits */ onRemoveUploadedFile = output(); /** * Custom file template. * @group Templates */ fileTemplate = contentChild('file', { ...(ngDevMode ? { debugName: "fileTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom header template. * @param {FileUploadHeaderTemplateContext} context - header template context. * @group Templates */ headerTemplate = contentChild('header', { ...(ngDevMode ? { debugName: "headerTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom content template. * @param {FileUploadContentTemplateContext} context - content template context. * @group Templates */ contentTemplate = contentChild('content', { ...(ngDevMode ? { debugName: "contentTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom toolbar template. * @group Templates */ toolbarTemplate = contentChild('toolbar', { ...(ngDevMode ? { debugName: "toolbarTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom choose icon template. * @group Templates */ chooseIconTemplate = contentChild('chooseicon', { ...(ngDevMode ? { debugName: "chooseIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom file label template. * @param {FileUploadFileLabelTemplateContext} context - file label template context. * @group Templates */ fileLabelTemplate = contentChild('filelabel', { ...(ngDevMode ? { debugName: "fileLabelTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom upload icon template. * @group Templates */ uploadIconTemplate = contentChild('uploadicon', { ...(ngDevMode ? { debugName: "uploadIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom cancel icon template. * @group Templates */ cancelIconTemplate = contentChild('cancelicon', { ...(ngDevMode ? { debugName: "cancelIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom empty state template. * @group Templates */ emptyTemplate = contentChild('empty', { ...(ngDevMode ? { debugName: "emptyTemplate" } : /* istanbul ignore next */ {}), descendants: false }); isAdvancedMode = computed(() => this.mode() === 'advanced', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "isAdvancedMode" }] : /* istanbul ignore next */ [])); isBasicMode = computed(() => this.mode() === 'basic', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "isBasicMode" }] : /* istanbul ignore next */ [])); showUploadBtn = computed(() => !this.auto() && this.showUploadButton(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "showUploadBtn" }] : /* istanbul ignore next */ [])); showCancelBtn = computed(() => !this.auto() && this.showCancelButton(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "showCancelBtn" }] : /* istanbul ignore next */ [])); chooseButtonDisabled = computed(() => this.disabled() || this.isChooseDisabled(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "chooseButtonDisabled" }] : /* istanbul ignore next */ [])); uploadButtonDisabled = computed(() => !this.hasFiles() || this.isFileLimitExceeded(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "uploadButtonDisabled" }] : /* istanbul ignore next */ [])); cancelButtonDisabled = computed(() => !this.hasFiles() || this.uploading(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "cancelButtonDisabled" }] : /* istanbul ignore next */ [])); showEmpty = computed(() => !!this.emptyTemplate() && !this.hasFiles() && !this.hasUploadedFiles(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "showEmpty" }] : /* istanbul ignore next */ [])); get headerTemplateContext() { return { $implicit: this.files, uploadedFiles: this.uploadedFiles(), chooseCallback: this.choose.bind(this), clearCallback: this.clear.bind(this), uploadCallback: this.upload.bind(this) }; } get contentTemplateContext() { return { $implicit: this.files, uploadedFiles: this.uploadedFiles(), chooseCallback: this.choose.bind(this), clearCallback: this.clear.bind(this), removeUploadedFileCallback: this.removeUploadedFile.bind(this), removeFileCallback: this.remove.bind(this), progress: this.progress(), messages: this.msgs() }; } get fileLabelTemplateContext() { return { $implicit: this.files }; } advancedFileInput = viewChild('advancedfileinput', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "advancedFileInput" }] : /* istanbul ignore next */ [])); basicFileInput = viewChild('basicfileinput', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "basicFileInput" }] : /* istanbul ignore next */ [])); contentEl = viewChild('content', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "contentEl" }] : /* istanbul ignore next */ [])); /** * Files input. * @group Props */ filesInput = input([], { ...(ngDevMode ? { debugName: "filesInput" } : /* istanbul ignore next */ {}), alias: 'files' }); get files() { return this._files(); } set files(value) { this._files.set(value); } get basicButtonLabel() { if (this.auto() || !this.hasFiles()) { return this.chooseLabel(); } return this.uploadLabel() ?? this.files[0].name; } _files = signal([], /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "_files" }] : /* istanbul ignore next */ [])); progress = signal(0, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "progress" }] : /* istanbul ignore next */ [])); dragHighlight = signal(false, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "dragHighlight" }] : /* istanbul ignore next */ [])); msgs = signal([], /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "msgs" }] : /* istanbul ignore next */ [])); uploadedFileCount = 0; focus = signal(false, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "focus" }] : /* istanbul ignore next */ [])); uploading = signal(false, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "uploading" }] : /* istanbul ignore next */ [])); duplicateIEEvent; // flag to recognize duplicate onchange event for file input translationSubscription; dragOverListener; uploadedFiles = signal([], /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "uploadedFiles" }] : /* istanbul ignore next */ [])); sanitizer = inject(DomSanitizer); http = inject(HttpClient); _componentStyle = inject(FileUploadStyle); constructor() { super(); effect(() => { const inputFiles = this.filesInput(); if (inputFiles && inputFiles.length > 0) { const newFiles = []; for (let i = 0; i < inputFiles.length; i++) { let file = inputFiles[i]; if (this.validate(file)) { if (this.isImage(file)) { file.objectURL = this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(inputFiles[i])); } newFiles.push(inputFiles[i]); } } this._files.set(newFiles); } }); } onInit() { this.translationSubscription = this.config.translationObserver.subscribe(() => { this.cd.markForCheck(); }); } onAfterViewInit() { if (isPlatformBrowser(this.platformId)) { if (this.mode() === 'advanced') { const contentEl = this.contentEl(); if (contentEl) { this.dragOverListener = this.renderer.listen(contentEl.nativeElement, 'dragover', this.onDragOver.bind(this)); } } } } basicFileChosenLabel() { if (this.auto()) return this.chooseButtonLabel; else if (this.hasFiles()) { if (this.files && this.files.length === 1) return this.files[0].name; return this.translate('fileChosenMessage')?.replace('{0}', this.files.length.toString()); } return this.translate('noFileChosenMessage') || ''; } completedLabel() { return this.translate('completed') || ''; } choose() { this.advancedFileInput()?.nativeElement.click(); } onFileSelect(event) { if (event.type !== 'drop' && this.isIE11() && this.duplicateIEEvent) { this.duplicateIEEvent = false; return; } if (!this.multiple()) { this.files = []; } this.msgs.set([]); this.files = this.files || []; let files = event.dataTransfer ? event.dataTransfer.files : event.target.files; for (let i = 0; i < files.length; i++) { let file = files[i]; if (!this.isFileSelected(file)) { if (this.validate(file)) { if (this.isImage(file)) { file.objectURL = this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(files[i])); } this.files.push(files[i]); } } } this.files = [...this.files]; this.onSelect.emit({ originalEvent: event, files: files, currentFiles: this.files }); // this will check the fileLimit with the uploaded files this.checkFileLimit(files); if (this.hasFiles() && this.auto() && (this.mode() !== 'advanced' || !this.isFileLimitExceeded())) { this.upload(); } if (event.type !== 'drop' && this.isIE11()) { this.clearIEInput(); } else { this.clearInputElement(); } } isFileSelected(file) { for (let sFile of this.files) { if (sFile.name + sFile.type + sFile.size === file.name + file.type + file.size) { return true; } } return false; } isIE11() { if (isPlatformBrowser(this.platformId)) { return !!this.document.defaultView['MSInputMethodContext'] && !!this.document['documentMode']; } } validate(file) { const acceptVal = this.accept(); if (acceptVal && !this.isFileTypeValid(file)) { const text = `${this.invalidFileTypeMessageSummary().replace('{0}', file.name)} ${this.invalidFileTypeMessageDetail().replace('{0}', acceptVal)}`; this.msgs.update((msgs) => [...msgs, { severity: 'error', text }]); return false; } const maxFileSizeVal = this.maxFileSize(); if (maxFileSizeVal && file.size > maxFileSizeVal) { const text = `${this.invalidFileSizeMessageSummary().replace('{0}', file.name)} ${this.invalidFileSizeMessageDetail().replace('{0}', this.formatSize(maxFileSizeVal))}`; this.msgs.update((msgs) => [...msgs, { severity: 'error', text }]); return false; } return true; } isFileTypeValid(file) { const acceptVal = this.accept(); let acceptableTypes = acceptVal?.split(',').map((type) => type.trim()); for (let type of acceptableTypes) { let acceptable = this.isWildcard(type) ? this.getTypeClass(file.type) === this.getTypeClass(type) : file.type == type || this.getFileExtension(file).toLowerCase() === type.toLowerCase(); if (acceptable) { return true; } } return false; } getTypeClass(fileType) { return fileType.substring(0, fileType.indexOf('/')); } isWildcard(fileType) { return fileType.indexOf('*') !== -1; } getFileExtension(file) { return '.' + file.name.split('.').pop(); } isImage(file) { return /^image\//.test(file.type); } onImageLoad(img) { window.URL.revokeObjectURL(img.src); } /** * Uploads the selected files. * @group Method */ uploader() { if (this.customUpload()) { const fileLimitVal = this.fileLimit(); if (fileLimitVal) { this.uploadedFileCount += this.files.length; } this.uploadHandler.emit({ files: this.files }); } else { this.uploading.set(true); this.msgs.set([]); let formData = new FormData(); this.onBeforeUpload.emit({ formData: formData }); const nameVal = this.name(); for (let i = 0; i < this.files.length; i++) { formData.append(nameVal, this.files[i], this.files[i].name); } this.http .request(this.method(), this.url(), { body: formData, headers: this.headers(), reportProgress: true, observe: 'events', withCredentials: this.withCredentials() }) .subscribe({ next: (event) => { switch (event.type) { case HttpEventType.Sent: this.onSend.emit({ originalEvent: event, formData: formData }); break; case HttpEventType.Response: this.uploading.set(false); this.progress.set(0); if (event['status'] >= 200 && event['status'] < 300) { const fileLimitVal = this.fileLimit(); if (fileLimitVal) { this.uploadedFileCount += this.files.length; } this.onUpload.emit({ originalEvent: event, files: this.files }); } else { this.onError.emit({ files: this.files }); } this.uploadedFiles.update((files) => [...files, ...this.files]); this.clear(); break; case HttpEventType.UploadProgress: { if (event['loaded']) { this.progress.set(Math.round((event['loaded'] * 100) / event['total'])); } this.onProgress.emit({ originalEvent: event, progress: this.progress() }); break; } } }, error: (error) => { this.uploading.set(false); this.onError.emit({ files: this.files, error: error }); } }); } } onRemoveClick(e) { const { event, index } = e; if (this.hasFiles()) { this.remove(event, index); } } onRemoveUploadedFileClick(e) { const { index } = e; if (this.hasUploadedFiles()) { this.removeUploadedFile(index); } } /** * Clears the files list. * @group Method */ clear() { this.files = []; this.onClear.emit(); this.clearInputElement(); this.msgs.set([]); } /** * Removes a single file. * @param {Event} event - Browser event. * @param {Number} index - Index of the file. * @group Method */ remove(event, index) { this.clearInputElement(); this.onRemove.emit({ originalEvent: event, file: this.files[index] }); this.files.splice(index, 1); this.files = [...this.files]; this.checkFileLimit(this.files); } /** * Removes uploaded file. * @param {Number} index - Index of the file to be removed. * @group Method */ removeUploadedFile(index) { const currentFiles = this.uploadedFiles(); const removedFile = currentFiles[index]; this.uploadedFiles.set(currentFiles.filter((_, i) => i !== index)); this.onRemoveUploadedFile.emit({ file: removedFile, files: this.uploadedFiles() }); } isFileLimitExceeded() { const isAutoMode = this.auto(); const totalFileCount = isAutoMode ? this.files.length : this.files.length + this.uploadedFileCount; const fileLimitVal = this.fileLimit(); if (fileLimitVal && fileLimitVal <= totalFileCount && this.focus()) { this.focus.set(false); } return fileLimitVal && fileLimitVal < totalFileCount; } isChooseDisabled() { const fileLimitVal = this.fileLimit(); if (this.auto()) { return fileLimitVal && fileLimitVal <= this.files.length; } else { return fileLimitVal && fileLimitVal <= this.files.length + this.uploadedFileCount; } } checkFileLimit(files) { const fileLimitVal = this.fileLimit(); const currentMsgs = this.msgs(); const hasExistingValidationMessages = currentMsgs.length > 0 && fileLimitVal && fileLimitVal < files.length; if (this.isFileLimitExceeded() || hasExistingValidationMessages) { const text = `${this.invalidFileLimitMessageSummary().replace('{0}', fileLimitVal.toString())} ${this.invalidFileLimitMessageDetail().replace('{0}', fileLimitVal.toString())}`; this.msgs.update((msgs) => [...msgs, { severity: 'error', text }]); } else { this.msgs.update((msgs) => msgs.filter((msg) => !msg.text.includes(this.invalidFileLimitMessageSummary()))); } } clearInputElement() { const advancedInput = this.advancedFileInput(); if (advancedInput && advancedInput.nativeElement) { advancedInput.nativeElement.value = ''; } const basicInput = this.basicFileInput(); if (basicInput && basicInput.nativeElement) { basicInput.nativeElement.value = ''; } } clearIEInput() { const advancedInput = this.advancedFileInput(); if (advancedInput && advancedInput.nativeElement) { this.duplicateIEEvent = true; //IE11 fix to prevent onFileChange trigger again advancedInput.nativeElement.value = ''; } } hasFiles() { return this.files && this.files.length > 0; } hasUploadedFiles() { return this.uploadedFiles().length > 0; } getFileTemplateContext(file) { return { $implicit: file }; } onDragEnter(e) { if (!this.disabled()) { e.stopPropagation(); e.preventDefault(); } } onDragOver(e) { if (!this.disabled()) { const contentEl = this.contentEl(); !this.$unstyled() && addClass(contentEl?.nativeElement, 'p-fileupload-highlight'); contentEl?.nativeElement.setAttribute('data-p-highlight', true); this.dragHighlight.set(true); e.stopPropagation(); e.preventDefault(); } } onDragLeave(_event) { if (!this.disabled()) { const contentEl = this.contentEl(); !this.$unstyled() && removeClass(contentEl?.nativeElement, 'p-fileupload-highlight'); contentEl?.nativeElement.setAttribute('data-p-highlight', false); } } onDrop(event) { if (!this.disabled()) { const contentEl = this.contentEl(); !this.$unstyled() && removeClass(contentEl?.nativeElement, 'p-fileupload-highlight'); contentEl?.nativeElement.setAttribute('data-p-highlight', false); event.stopPropagation(); event.preventDefault(); let files = event.dataTransfer ? event.dataTransfer.files : event.target.files; let allowDrop = this.multiple() || (files && files.length === 1); if (allowDrop) { this.onFileSelect(event); } } } onFocus() { this.focus.set(true); } onBlur() { this.focus.set(false); } formatSize(bytes) { const k = 1024; const dm = 3; const sizes = this.translate(TranslationKeys.FILE_SIZE_TYPES); if (bytes === 0) { return `0 ${sizes[0]}`; } const i = Math.floor(Math.log(bytes) / Math.log(k)); const formattedSize = (bytes / Math.pow(k, i)).toFixed(dm); return `${formattedSize} ${sizes[i]}`; } upload() { if (this.hasFiles()) this.uploader(); } onBasicUploaderClick() { this.basicFileInput()?.nativeElement.click(); } onBasicKeydown(event) { switch (event.code) { case 'Space': case 'Enter': this.onBasicUploaderClick(); event.preventDefault(); break; } } imageError(event) { this.onImageError.emit(event); } getBlockableElement() { return this.el.nativeElement.children[0]; } get chooseButtonLabel() { return this.chooseLabel() || this.translate(TranslationKeys.CHOOSE); } get uploadButtonLabel() { return this.uploadLabel() || this.translate(TranslationKeys.UPLOAD); } get cancelButtonLabel() { return this.cancelLabel() || this.translate(TranslationKeys.CANCEL); } get browseFilesLabel() { return this.translate(TranslationKeys.ARIA, TranslationKeys.BROWSE_FILES); } get pendingLabel() { return this.translate(TranslationKeys.PENDING); } onDestroy() { const contentEl = this.contentEl(); if (contentEl && contentEl.nativeElement) { if (this.dragOverListener) { this.dragOverListener(); this.dragOverListener = null; } } if (this.translationSubscription) { this.translationSubscription.unsubscribe(); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FileUpload, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: FileUpload, isStandalone: true, selector: "p-fileupload", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null }, method: { classPropertyName: "method", publicName: "method", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, auto: { classPropertyName: "auto", publicName: "auto", isSignal: true, isRequired: false, transformFunction: null }, withCredentials: { classPropertyName: "withCredentials", publicName: "withCredentials", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, invalidFileSizeMessageSummary: { classPropertyName: "invalidFileSizeMessageSummary", publicName: "invalidFileSizeMessageSummary", isSignal: true, isRequired: false, transformFunction: null }, invalidFileSizeMessageDetail: { classPropertyName: "invalidFileSizeMessageDetail", publicName: "invalidFileSizeMessageDetail", isSignal: true, isRequired: false, transformFunction: null }, invalidFileTypeMessageSummary: { classPropertyName: "invalidFileTypeMessageSummary", publicName: "invalidFileTypeMessageSummary", isSignal: true, isRequired: false, transformFunction: null }, invalidFileTypeMessageDetail: { classPropertyName: "invalidFileTypeMessageDetail", publicName: "invalidFileTypeMessageDetail", isSignal: true, isRequired: false, transformFunction: null }, invalidFileLimitMessageDetail: { classPropertyName: "invalidFileLimitMessageDetail", publicName: "invalidFileLimitMessageDetail", isSignal: true, isRequired: false, transformFunction: null }, invalidFileLimitMessageSummary: { classPropertyName: "invalidFileLimitMessageSummary", publicName: "invalidFileLimitMessageSummary", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, previewWidth: { classPropertyName: "previewWidth", publicName: "previewWidth", isSignal: true, isRequired: false, transformFunction: null }, chooseLabel: { classPropertyName: "chooseLabel", publicName: "chooseLabel", isSignal: true, isRequired: false, transformFunction: null }, uploadLabel: { classPropertyName: "uploadLabel", publicName: "uploadLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelLabel: { classPropertyName: "cancelLabel", publicName: