Search results

Template

You can customize the default appearance of the uploader using a template along with buttons.

File list template

The templateproperty is used to customize the default appearance of each file in the list. It can be represented as the HTML element or string. The selected or dropped files are displayed as per the template layout provided. The remove and progress bar action is handled using the corresponding events when the template is defined.

For example, you can display file type icon along with the default UI elements.

Source
Preview
index.tsx
index.html
import {  detach, select } from '@syncfusion/ej2-base';
import { SelectedEventArgs, UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";

export default class App extends React.Component<{}, {}> {
     public uploadObj: UploaderComponent;
      public path: object = {
        removeUrl: 'https://aspnetmvc.syncfusion.com/services/api/uploadbox/Remove',
        saveUrl: 'https://aspnetmvc.syncfusion.com/services/api/uploadbox/Save'
      }
        private dropAreaRef: HTMLElement;
        public onCreated(): void {
            this.uploadObj.dropArea = this.dropAreaRef;
            this.uploadObj.dataBind();
        }
        public dropAreaClick(args: any): void {
            const target: any = args.target as HTMLElement;
        if (target.classList.contains('e-file-delete-btn')) {
            for (const i of  this.uploadObj.getFilesData()) {
                if (target.closest('li').getAttribute('data-file-name') === i.name) {
                    this.uploadObj.remove(this.uploadObj.getFilesData()[this.uploadObj.getFilesData().indexOf(i)]);
                }
            }
        } else if (target.classList.contains('e-file-remove-btn')) {
            detach(target.closest('li'));
        }
        }
        public browseClick(args: any): any {
          const wrapperEle: HTMLElement = select('.e-file-select-wrap button', document) as HTMLElement;
          wrapperEle.click();
          args.preventDefault();
        }

        public onFileUpload(args: any): void {
            const li: HTMLElement = this.dropAreaRef.querySelector('[data-file-name="' + args.file.name + '"]') as any;
            const progressValue: number = Math.round((args.e.loaded / args.e.total) * 100);
            li.getElementsByTagName('progress')[0].value = progressValue;
            li.getElementsByClassName('percent')[0].textContent = progressValue.toString() + " %";
        }
        public onuploadSuccess(args: any): void {
            if (args.operation === 'remove') {
                let height: any = this.dropAreaRef.style.height;
                height = (parseInt(height, 10) - 40) + 'px';
                this.dropAreaRef.style.height = height;
            } else {
                const li: HTMLElement = this.dropAreaRef.querySelector('[data-file-name="' + args.file.name + '"]') as any;
                const progressBar: HTMLElement = li.getElementsByTagName('progress')[0];
                progressBar.classList.add('e-upload-success');
                li.getElementsByClassName('percent')[0].classList.add('e-upload-success');
                const height: any = this.dropAreaRef.style.height;
                this.dropAreaRef.style.height = parseInt(height, 10) - 15 + 'px';
            }
        }
        public onSelect(args: SelectedEventArgs): void {
            const length: number = args.filesData.length;
            let height: any = this.dropAreaRef.style.height;
            height = parseInt(height, 10) + (length * 55) + 'px';
            this.dropAreaRef.style.height = height;
        }
        public onuploadFailed(args: any): void {
            const li: HTMLElement = this.dropAreaRef.querySelector('[data-file-name="' + args.file.name + '"]') as any;
            const progressBar: HTMLElement = li.getElementsByTagName('progress')[0];
            progressBar.classList.add('e-upload-failed');
            li.getElementsByClassName('percent')[0].classList.add('e-upload-failed');
        }
 public uploaderTemplate(data: any): JSX.Element {
        return (
            <div>
            <span className='wrapper'>
                <span className={'icon template-icons sf-icon-${data.type}'} />
                <span className='name file-name'>{data.name}</span>
            </span>
                <span className='file-size-td file-size'>{data.size} bytes</span>
                <span className='e-icons e-file-remove-btn' title='Remove' /> <br/>
                <progress id='progressBar' className='progressbar' value='0' max='100' />
                <span className='percent-td percent' />
            </div>);
        }

  public render(): JSX.Element{
    return (
        <div id='dropArea' onClick={this.dropAreaClick = this.dropAreaClick.bind(this)} ref={dropEle => {this.dropAreaRef = dropEle!}}>
        <span id='drop'> Drop files here or <a href="" id='browse' onClick={this.browseClick = this.browseClick.bind(this)}><u>Browse</u></a> </span>
        <UploaderComponent id='UploadFiles'  ref = {upload => {this.uploadObj = upload !}} asyncSettings={this.path}
        progress={this.onFileUpload = this.onFileUpload.bind(this)} selected={this.onSelect = this.onSelect.bind(this)} success={this.onuploadSuccess = this.onuploadSuccess.bind(this)} failure={this.onuploadFailed = this.onuploadFailed.bind(this)} template={this.uploaderTemplate} created={this.onCreated = this.onCreated.bind(this)}/>
    </div>);
  }
}

ReactDOM.render(<App />, document.getElementById('fileupload'));
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Syncfusion React Uploader</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Essential JS 2 for React Components" />
    <meta name="author" content="Syncfusion" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-buttons/styles/material.css" rel="stylesheet" />
    <link href="style.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
    <style>
        #loader {
            color: #008cff;
            height: 40px;
            left: 45%;
            position: absolute;
            top: 45%;
            width: 30%;
        }
    </style>
</head>

<body>
    <div id='fileupload' style="margin: 20px auto 0; width:450px;">
        <div id='loader'>Loading....</div>
    </div>
</body>

</html>

Custom template

You can design the own template by preventing the default file list including buttons. The showFileList property used to display whether the default file list or own file list When you use custom template to upload or remove the files, pass the custom UI argument as true to call upload/remove public method as follows:

  • UploaderObj.upload(filesData, true);

  • UploaderObj.remove(filesData, true);

Refer to the following code sample.

Source
Preview
index.tsx
index.html
import { createElement, detach, EventHandler, isNullOrUndefined, select } from '@syncfusion/ej2-base';
import { FileInfo, RemovingEventArgs, UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";

export default class App extends React.Component<{}, {}> {
    constructor() {
        super()
        this.removeFiles = this.removeFiles.bind(this);
    }
    public uploadObj: UploaderComponent;
    public parentElement : HTMLElement; public proxy : any; public progressbarContainer : HTMLElement;
    public filesDetails : FileInfo[] = [];
    public filesList: HTMLElement[] = [];
      public path: object = {
        removeUrl: 'https://aspnetmvc.syncfusion.com/services/api/uploadbox/Remove/',
        saveUrl: 'https://aspnetmvc.syncfusion.com/services/api/uploadbox/Save/'
      }
      private dropAreaEle: HTMLElement;
        private dropAreaRef: HTMLElement;
        public onCreated(): void {
            this.uploadObj.dropArea = this.dropAreaRef;
            this.uploadObj.dataBind();
        }
    public browseClick(args: any): any {
        const wrapperEle: HTMLElement = select('.e-file-select-wrap button', document) as HTMLElement;
        wrapperEle.click();
        args.preventDefault();
    }
    public onSuccess(args: any) : void {
      const li: any =  this.dropAreaRef.querySelector('[data-file-name="' + args.file.name + '"]') as HTMLElement;
      if (args.operation === 'upload') {
          li.querySelector('.close-icon-container').classList.add('delete-icon');
          detach(li.getElementsByTagName('progress')[0]);
          (li.querySelector('.file-size') as HTMLElement).style.display = 'inline-block';
          (li.querySelector('.file-name') as HTMLElement).style.color = 'green';
      } else {
          this.uploadObj.element.value = '';
          detach(li);
      }
      EventHandler.add(li.querySelector('.close-icon-container'), 'click', this.removeFiles, this);
  }

public onFileSelect(args : any) : void  {
      if ((this.dropAreaRef.querySelector('.upload-list-root')) === null) {
          this.parentElement = createElement('div', { className: 'upload-list-root' });
          this.parentElement.appendChild(createElement('ul', {className: 'ul-element' }));
         this.dropAreaRef.appendChild(this.parentElement);
      }
      for (const i of args.filesData) {
          this.formSelectedData(i, this);  // create the LI element for each file Data
      }
      this.filesDetails = this.filesDetails.concat(args.filesData);
      this.uploadObj.upload(args.filesData, true);
      args.cancel = true;
  }

  public formSelectedData ( selectedFiles : FileInfo, proxy: any ) : void {
      const liEle : any = createElement('li',  { className: 'file-lists', attrs: {'data-file-name' : selectedFiles.name} });
      liEle.appendChild(createElement('span', {className: 'file-name ', innerHTML: selectedFiles.name }));
      liEle.appendChild(createElement('span', {className: 'file-size ', innerHTML: this.uploadObj.bytesToSize(selectedFiles.size) }));
      if (selectedFiles.statusCode === '1') {
          this.progressbarContainer = createElement('span', {className: 'progress-bar-container'});
          this.progressbarContainer.appendChild(createElement('progress', {className: 'progress', attrs: {value : '0', max : '100'}} ));
          liEle.appendChild(this.progressbarContainer);
      } else { liEle.querySelector('.file-name').classList.add('upload-fails'); }
      const closeIconContainer : HTMLElement = createElement('span', {className: 'e-icons close-icon-container'});
      EventHandler.add(closeIconContainer, 'click', this.removeFiles, proxy);
      liEle.appendChild(closeIconContainer);
      (document as any).querySelector('.ul-element').appendChild(liEle);
      this.filesList.push(liEle);
  }

  public onFileUpload(args : any) : void {
      const li : any = this.dropAreaRef.querySelector('[data-file-name="' + args.file.name + '"]');
      EventHandler.remove(li.querySelector('.close-icon-container'), 'click', this.removeFiles);
      const progressValue : number = Math.round((args.e.loaded / args.e.total) * 100);
      if (!isNaN(progressValue)) {
          li.getElementsByTagName('progress')[0].value = progressValue;   // Updating the progress bar value
      }
  }

  public onUploadFailed(args : any) : void {
      const li : any = this.dropAreaRef.querySelector('[data-file-name="' + args.file.name + '"]');
      EventHandler.add(li.querySelector('.close-icon-container'), 'click', this.removeFiles, this);
      li.querySelector('.file-name ').classList.add('upload-fails');
      if (args.operation === 'upload') {
          detach(li.querySelector('.progress-bar-container'));
      }
  }
  public removeFiles(args : any) : void {
      const status : string = this.filesDetails[this.filesList.indexOf(args.currentTarget.parentElement)].statusCode;
      if (status === '2') {
          this.uploadObj.remove(this.filesDetails[this.filesList.indexOf(args.currentTarget.parentElement)]);
      } else {
          detach(args.currentTarget.parentElement);
      }
  }
  public onuploadFailed(args: any): void {
        const li: HTMLElement = this.dropAreaRef.querySelector('[data-file-name="' + args.file.name + '"]') as any;
        const progressBar: HTMLElement = li.getElementsByTagName('progress')[0];
        progressBar.classList.add('e-upload-failed');
        li.getElementsByClassName('percent')[0].classList.add('e-upload-failed');
    }
    public onFileRemove(args: RemovingEventArgs): void {
        args.postRawFile = false;
    }
  public render():JSX.Element{
    return (
      <div id='dropArea' className='dropArea' ref={dropAreaEle => this.dropAreaRef = dropAreaEle!}>
        <span id='drop' className='file-name-span drop'> Drop files here or <a href="" id='browse' onClick={this.browseClick = this.browseClick.bind(this)}><u>Browse</u></a> </span>
          <UploaderComponent id='fileUpload' type = 'file' ref = {upload => {this.uploadObj = upload !}}
            asyncSettings = {this.path}
            success={ this.onSuccess = this.onSuccess.bind(this) }
            selected= { this.onFileSelect = this.onFileSelect.bind(this) }
            progress = {this.onFileUpload = this.onFileUpload.bind(this) }
            failure = { this.onUploadFailed = this.onUploadFailed.bind(this) } created={this.onCreated = this.onCreated.bind(this)} removing={this.onFileRemove = this.onFileRemove.bind(this)}/>
      </div>);
    }
}

ReactDOM.render(<App />, document.getElementById('fileupload'));
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Syncfusion React Uploader</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Essential JS 2 for React Components" />
    <meta name="author" content="Syncfusion" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-buttons/styles/material.css" rel="stylesheet" />
    <link href="style.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>

</head>

<body>
    <div id='fileupload' style="margin: 20px auto 0; width:450px;">
        <div id='loader'>Loading....</div>
    </div>
</body>

</html>

See Also