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
JavaScript
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: