{
  "$schema": "https://ai.syncfusion.com/schema/registry-item.json",
  "name": "pdf-viewer-multi-format-viewer",
  "framework": "angular",
  "type": "registry:component",
  "component": "PdfViewer",
  "variant": "multi-format-viewer",
  "dependencies": [
    "@syncfusion/ej2-angular-pdfviewer"
  ],
  "description": "PDF viewer sample for displaying PDF and other supported document formats.",
  "meta": {
    "essentialStudioRelease": "2026 Volume 2 (v34.1.29)",
    "license": "commercial-or-community",
    "licenseNote": "The Syncfusion package is licensed. The composition in this file is source you own and edit. See https://ai.syncfusion.com/licensing.md",
    "requiresLicenseKey": true,
    "requiresServerEndpoint": true,
    "platformIndex": "https://ai.syncfusion.com/angular/llms.txt",
    "skillPack": "syncfusion/angular-ui-components-skills",
    "docs": "https://ai.syncfusion.com/gallery/angular/pdf-viewer-multi-format-viewer.md"
  },
  "files": [
    {
      "target": "src/components/pdf-viewer-multi-format-viewer/multi-format-viewer.component.ts",
      "content": "import { Component, ViewEncapsulation, OnInit, ViewChild, ElementRef } from '@angular/core';\nimport {\n  PdfViewerComponent,\n  LinkAnnotationService,\n  BookmarkViewService,\n  MagnificationService,\n  ThumbnailViewService,\n  ToolbarService,\n  NavigationService,\n  AnnotationService,\n  TextSearchService,\n  TextSelectionService,\n  PrintService,\n  FormFieldsService,\n  FormDesignerService,\n  PdfViewerModule,\n  PageOrganizerService\n} from '@syncfusion/ej2-angular-pdfviewer';\nimport { UploaderComponent, UploaderModule } from '@syncfusion/ej2-angular-inputs';\nimport { SwitchModule } from '@syncfusion/ej2-angular-buttons';\nimport { AnimationModel, ProgressTheme, ILoadedEventArgs, ProgressBar } from '@syncfusion/ej2-progressbar';\nimport { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';\n\n@Component({\n  selector: 'control-content',\n  templateUrl: 'multi-format-viewer.html',\n  encapsulation: ViewEncapsulation.None,\n  providers: [\n    LinkAnnotationService,\n    BookmarkViewService,\n    MagnificationService,\n    ThumbnailViewService,\n    ToolbarService,\n    NavigationService,\n    AnnotationService,\n    TextSearchService,\n    TextSelectionService,\n    PrintService,\n    FormFieldsService,\n    FormDesignerService,\n    PageOrganizerService\n  ],\n  standalone: true,\n    imports: [\n        SwitchModule,\n        PdfViewerModule,\n        UploaderModule,\n        ProgressBarModule\n    ],\n})\n\nexport class MultiFormatViewerComponent implements OnInit {\n  @ViewChild('pdfviewer') public pdfviewerControl!: PdfViewerComponent;\n  @ViewChild('templateupload') public uploadObj!: UploaderComponent;\n  @ViewChild('linear')\n  public linear!: ProgressBar;\n  public resource: string = 'https://cdn.syncfusion.com/ej2/23.2.6/dist/ej2-pdfviewer-lib';\n  public dropElement: any;\n  public extensions: any = ['doc','docx','rtf','docm','dotm','dotx','dot','xls','xlsx','pptx','pptm','potx','potm','jpeg','png','bmp','pdf','jpg'];\n  public allowedExtensions: string = '.doc, .docx, .rtf, .docm, .dotm, .dotx, .dot, .xls, .xlsx, .pptx, .pptm, .potx, .potm .jpeg, .png, .bmp, .pdf, .jpg';\n  public zoomMode = \"FitToPage\";\n  public toolbarSettings = {\n    showTooltip: true,\n    toolbarItems: [\n      'DownloadOption',\n      'UndoRedoTool',\n      'PageNavigationTool',\n      'MagnificationTool',\n      'PanTool',\n      'SelectionTool',\n      'CommentTool',\n      'SubmitForm',\n      'SearchOption',\n      'AnnotationEditTool',\n      'FormDesignerEditTool',\n      'PrintOption'\n    ]\n  };\n  fileList: any[] = [];\n  uploadProgressValue: number = 0;\n  pdfViewerProgressValue: number = 0;\n  public width: string = '250';\n  public height: string = '60';\n  public progressValue: any = 0;\n  public min: number = 0;\n  public max: number = 100;\n  public multipleFiles: boolean = false;\n  public animation: any = {enable: false, duration: 0, delay: 0};\n\n  ngOnInit(): void {\n    this.dropElement = document.getElementById('dropArea') as HTMLElement;\n    let browseButton = document.getElementById('browse');\n    if (browseButton) {\n      browseButton.onclick = () => {\n        document.getElementsByClassName('e-file-select-wrap')![0].querySelector('button')!.click();\n        return false;\n      };\n    }\n  }\n\n\n  documentLoaded(): void {\n    let progressValue: any = document.getElementById(\"progress-status\")as HTMLElement;\n    this.pdfViewerProgressValue = 100;\n    const totalProgress = this.calculateTotalProgress();\n    this.updateProgressBar(totalProgress);\n    progressValue.innerHTML = totalProgress.toString()+\"%\";\n    setTimeout(()=>{\n      document.getElementById(\"linearProgressBar\")!.style.display = \"none\";\n      document.getElementById(\"uploadedMessage\")!.style.display = \"block\"\n      this.uploadProgressValue = 0;\n      this.pdfViewerProgressValue = 0;\n      progressValue.innerHTML = \"0%\";\n      this.progressValue = 0;\n      this.linear.value = 0;\n      this.linear.refresh();\n    },1000);\n  }\n\n  onSelect(args: any) {\n    let progressBarContainer: any = document.getElementById(\"progressBar\") as HTMLElement;\n    let progressBar: any = document.getElementById(\"linearProgressBar\") as HTMLElement;\n    let progressMessage: any = document.getElementById(\"uploadedMessage\") as HTMLElement;\n    let fileSupportMessage = document.getElementById(\"fileSupportMessage\")as HTMLElement;\n    let fileDetails = document.getElementById(\"file-details\")as HTMLElement;\n    let fileSizeValidation = document.getElementById(\"fileSizeValidation\")as HTMLElement;\n    progressBarContainer.style.display = \"block\";\n    progressBar.style.display = \"flex\";\n    progressMessage.style.display = \"none\"\n    fileSupportMessage.style.display = \"none\";\n    fileSizeValidation.style.display = \"none\";\n    let dropElement = document.getElementById('dropArea');\n    if (!dropElement!.querySelector('li')) {\n      this.fileList = [];\n    }\n    if (!dropElement!.querySelector('.e-upload-files')) {\n      let parentElement = document.createElement('ul');\n      parentElement.className = 'e-upload-files';\n      document.querySelector('.e-upload')!.appendChild(parentElement);\n    }\n    let validFiles = args.filesData;\n    if (validFiles.length === 0) {\n      progressBarContainer.style.display = \"block\";\n      progressBar.style.display = \"none\";\n      if(document.getElementById('pdfviewer-container')!.style.display === \"block\"){\n        progressMessage.style.display = \"block\";\n        fileDetails.style.display = \"block\";\n      }\n      args.cancel = true;\n      return;\n    }\n    if(!this.extensions.includes(validFiles[0].type)){\n      fileSupportMessage.style.display = \"block\";\n      progressBar.style.display = \"none\";\n      fileDetails.style.display = \"none\";\n      args.cancel = true;\n      return;\n    }\n    if(validFiles[0].type != \"pdf\" && validFiles[0].size>4000000){\n      fileSizeValidation.style.display = \"block\";\n      progressBar.style.display = \"none\";\n      fileDetails.style.display = \"none\";\n      args.cancel = true;\n      return;\n    }\n    fileDetails.style.display = \"block\";\n    document.getElementById(\"fileName\")!.innerHTML = args.filesData[0].name;\n    this.pdfviewerControl.downloadFileName = args.filesData[0].name;\n    this.pdfviewerControl.exportAnnotationFileName = args.filesData[0].name;\n    let size = document.getElementById(\"fileSize\") as HTMLElement;\n    if((args.filesData[0].size.toString()).length <= 6){\n      size.innerHTML = ((args.filesData[0].size/1024).toFixed(1)).toString()+\" KB\";\n    } else {\n      let kbsize = args.filesData[0].size/1024;\n      size.innerHTML = ((kbsize/1024).toFixed(1)).toString()+\" MB\";\n    }\n    this.formSelectedData(validFiles[0], this);\n    this.fileList = this.fileList.concat(validFiles);\n    const totalProgress = this.calculateTotalProgress();\n    this.updateProgressBar(totalProgress);\n    args.cancel = true;\n  }\n\n  formSelectedData(file : any, proxy : any) {\n    let liEle = document.createElement('li');\n    liEle.className = 'e-upload-file-list';\n    liEle.setAttribute('data-file-name', file.name);\n    this.readURL(liEle, file);\n    proxy.fileList.push(liEle);\n  }\n\n  readURL(li : any, args : any) {\n    let file = args.rawFile;\n    let reader = new FileReader();\n    let type = args.type;\n    reader.addEventListener('load', () => {\n      let post = JSON.stringify({\n        'data': reader.result,\n        'type': type\n      });\n      let url = 'https://document.syncfusion.com/web-services/pdf-viewer/api/pdfviewer/LoadFile';\n      let xhr = new XMLHttpRequest();\n      xhr.open('POST', url, true);\n      xhr.setRequestHeader('Content-type', 'application/json; charset=UTF-8');\n      xhr.upload.addEventListener('progress', (event) => {\n        if (event.lengthComputable) {\n          const progressValue = Math.round((event.loaded / event.total) * 100);\n          this.uploadProgressValue = progressValue;\n          const totalProgress = this.calculateTotalProgress();\n          (document.getElementById(\"progress-status\")as HTMLElement).innerHTML = totalProgress.toString()+\"%\";;\n          this.updateProgressBar(totalProgress);\n        }\n      });\n      xhr.onreadystatechange = (event: any) => {\n        if (xhr.readyState === XMLHttpRequest.DONE) {\n          if (xhr.status === 200) {\n            this.pdfviewerControl.documentPath = '';\n            this.pdfviewerControl.documentPath = xhr.responseText;\n            this.pdfViewerProgressValue = 60;\n            const totalProgress = this.calculateTotalProgress();\n            this.updateProgressBar(totalProgress);\n            (document.getElementById(\"progress-status\")as HTMLElement).innerHTML = totalProgress.toString()+\"%\";;\n            document.getElementById('pdfviewer-container')!.style.display = 'block';\n          } else {\n            console.error('Error:', xhr.statusText);\n          }\n        }\n      };\n      xhr.send(post);\n    }, false);\n    if (file) {\n      reader.readAsDataURL(file);\n    }\n  }\n\n  calculateTotalProgress(): number {\n    const totalProgress = (this.uploadProgressValue + this.pdfViewerProgressValue)/2;\n    return totalProgress;\n  }\n\n  updateProgressBar(progress: number): void {\n    if (this.linear) {\n      this.linear.value = progress;\n      this.linear.dataBind();\n    }\n  }\n\n  ajaxRequestSuccess(args: any): any{\n    let progressValue: any = document.getElementById(\"progress-status\")as HTMLElement;\n    if (args.action === \"Load\") {\n      this.pdfViewerProgressValue = 70;\n      const totalProgress = this.calculateTotalProgress();\n      this.updateProgressBar(totalProgress);\n      progressValue.innerHTML = totalProgress.toString()+\"%\";\n    }\n    if (args.action === \"RenderPdfPages\") {\n      if(this.pdfViewerProgressValue < 90){\n        this.pdfViewerProgressValue = this.pdfViewerProgressValue + 10;\n        const totalProgress = this.calculateTotalProgress();\n        this.updateProgressBar(totalProgress);\n        progressValue.innerHTML = totalProgress.toString()+\"%\";\n      }\n    }\n  }\n\n  public load(args: ILoadedEventArgs): void {\n    let selectedTheme: string = location.hash.split('/')[1];\n    selectedTheme = selectedTheme ? selectedTheme : 'Material';\n    args.progressBar.theme = <ProgressTheme>(selectedTheme.charAt(0).toUpperCase() +\n        selectedTheme.slice(1)).replace(/-dark/i, 'Dark').replace(/contrast/i, 'Contrast');\n    if (selectedTheme === 'fabric') {\n        args.progressBar.secondaryProgressColor = '#b0d0e9'\n    } else if (selectedTheme === 'material-dark') {\n        args.progressBar.secondaryProgressColor = '#b8b8b8'\n    } else if (selectedTheme === 'material') {\n        args.progressBar.secondaryProgressColor = '#f087ab'\n    } else if (selectedTheme === 'bootstrap5-dark') {\n        args.progressBar.secondaryProgressColor = '#2b5288'\n    } else if (selectedTheme === 'bootstrap5') {\n        args.progressBar.secondaryProgressColor = '#98c5f5'\n    } else if (selectedTheme === 'bootstrap') {\n        args.progressBar.secondaryProgressColor = '#acc6dc'\n    } else if (selectedTheme === 'bootstrap4') {\n        args.progressBar.secondaryProgressColor = '#98c5f5'\n    } else if (selectedTheme === 'bootstrap-dark') {\n        args.progressBar.secondaryProgressColor = '#b8b8b8'\n    } else if (selectedTheme === 'highcontrast') {\n        args.progressBar.secondaryProgressColor = '#aca379'\n    } else if (selectedTheme === 'fluent-dark') {\n        args.progressBar.secondaryProgressColor = '#2b5288'\n    } else if (selectedTheme === 'fluent') {\n        args.progressBar.secondaryProgressColor = '#98c5f5'\n    } else if (selectedTheme === 'tailwind-dark') {\n        args.progressBar.secondaryProgressColor = '#386e7f'\n    } else if (selectedTheme === 'tailwind') {\n        args.progressBar.secondaryProgressColor = '#b1afe9'\n    }\n  }\n}\n"
    },
    {
      "target": "src/components/pdf-viewer-multi-format-viewer/multi-format-viewer.html",
      "content": "<div class=\"control-section\">\n    <div class=\"content-wrapper\">\n        <div id=\"dropArea\" class=\"viewer-file-droparea\" style=\"height: auto; overflow: auto; margin-bottom: 25px;\">\n            <button ejs-button class=\"e-control e-btn e-lib\" id=\"browse\">Browse...</button>\n            <div>\n                <p style=\"margin: 15px;\">OR</p>\n                <p id=\"drop\">Drop files (Word, Excel, PowerPoint, Image, PDF)</p>\n            </div>\n            <div id=\"progressBar\" style=\"display: none;\">\n                <div id=\"file-details\">\n                    <p id=\"fileName\"></p>\n                    <p id=\"fileSize\"></p>\n                </div>\n                <div style=\"justify-content: center;\" id=\"linearProgressBar\">\n                    <progress #linear id=\"linear\" max=\"{{max}}\" style=\"width: fit-content; height: 20px;\"></progress><span id=\"progress-status\" style=\"padding: 18px 5px;\"></span>\n                </div>\n                <div id=\"uploadedMessage\" style=\"display: none; margin-top: 10px;\">\n                    <p style=\"color: rgb(110, 218, 110);\">File successfully uploaded...</p>\n                </div>\n                <div id=\"fileSupportMessage\" style=\"display: none; margin-top: 10px;\">\n                    <p style=\"color: rgb(203, 38, 38);\">File not supported!</p>\n                </div>\n                <div id=\"fileSizeValidation\" style=\"display: none; margin-top: 10px;\">\n                    <p style=\"color: rgb(203, 38, 38);\">Maximum file size is (4.0 MB) for this operation...</p>\n                </div>\n            </div>\n            <div style=\"display: none;\">\n                <ejs-uploader #templateupload id='templatefileupload' [dropArea]='dropElement' [allowedExtensions]=\"allowedExtensions\" (selected)='onSelect($event)'\n                [multiple]=\"multipleFiles\"></ejs-uploader>\n            </div>\n        </div>\n        <div id=\"pdfviewer-container\" style=\"display: none;\">\n            <ejs-pdfviewer #pdfviewer id=\"pdfViewer\" class=\"e-pv-multi-format-pdfviewer\" [zoomMode]=\"zoomMode\" [toolbarSettings]=\"toolbarSettings\" [resourceUrl]='resource' \n            (documentLoad)=\"documentLoaded()\" (ajaxRequestSuccess)=\"ajaxRequestSuccess($event)\" style=\"height:640px;\"></ejs-pdfviewer>\n        </div>\n    </div>\n</div>\n\n<style>\n    .content-wrapper .viewer-file-droparea {\n        border: 1px dashed #c3c3cc;\n        position: relative;\n        text-align: center;\n        padding: 20px 0 10px;\n    }\n\n    #pdfViewer_viewerContainer{\n        left: 0px !important;\n        width: 100% !important;\n    }\n\n    .e-pv-multi-format-pdfviewer .e-pv-text-search-bar {\n        top: 40px !important;\n    }\n\n    .e-bigger .e-pv-multi-format-pdfviewer .e-pv-text-search-bar {\n        top: 48px !important;\n    }\n</style>"
    }
  ]
}