PDF preview for files

Learn how to create an alternative PDF view for file preview.

First, let's create a new file called FilePreview_pdf.vue and copy the FilePreview template and add a preview for the PDF using <embed>:

vue
<!-- FilePreview_pdf.vue -->

<template>
  <div
    :class="classes.container"
    v-show="visible"
    v-bind="attrs"
    tabindex="0"
    role="button"
    :aria-labelledby="ariaLabelledby"
    :aria-placeholder="ariaPlaceholder"
    :aria-describedby="`${el$.fieldId}-file-description`"
    @keyup="handleKeyup"
  >
    <span :id="`${el$.fieldId}-file-description`" :class="classes.assistiveText" aria-hidden="">{{ form$.translations.vueform.a11y.file.description }}</span>

    <div :class="classes.wrapper">
      <div :class="classes.file">
        <!-- Filename -->
        <a :href="link" v-if="hasLink && clickable" :class="classes.filenameLink" target="_blank" rel="nofollow noopener">{{ filename }}</a>
        <span v-else :class="classes.filenameStatic">{{ filename }}</span>
      </div>
      
      <div :class="classes.actions">
        <!-- Remove -->
        <div
          v-if="canRemove"
          :class="classes.remove"
          @click.prevent="remove"
          @keypress.enter.space="remove"
          aria-roledescription="❎"
          role="button"
          tabindex="0"
        >
          <span :class="classes.removeIcon"></span>
        </div>

        <!-- Progress -->
        <div v-if="uploading" :class="classes.percent">{{ progress }}%</div>

        <!-- Error -->
        <span v-if="hasError" :class="classes.warning">
          <span :class="classes.warningIcon"></span>
        </span>

        <!-- Upload button -->
        <div
          v-if="canUploadTemp"
          :class="classes.upload"
          @click.prevent="upload"
          tabindex="-1"
        >{{ uploadText }}</div>

        <!-- Success -->
        <span v-else-if="el$.stage > 1" :class="classes.uploaded">
          <span :class="classes.uploadedIcon"></span>
        </span>
      </div>
    </div>

    <!-- PDF preview -->
    <div :class="classes.pdf_container">
      <embed :src="preview" :class="classes.pdf" />
    </div>

    <!-- Upload progress -->
    <div v-if="uploading" :class="classes.progressBar">
      <div :class="classes.progress" :style="{ width: progress + '%' }"></div>
    </div>
  </div>
</template>

<script>
import tailwindTheme from '@vueform/vueform/dist/tailwind'

export default {
  name: 'FilePreview_pdf',
  data() {
    return {
      merge: false,
      defaultClasses: {
        // Insert default classes
        ...tailwindTheme.classes.FilePreview,

        // Add pdf classes
        pdf_container: 'my-4',
        pdf: 'w-full h-[500px]',
      }
    }
  }
}
</script>
vue
<!-- FilePreview_pdf.vue -->

<template>
  <div
    :class="classes.container"
    v-show="visible"
    v-bind="attrs"
    tabindex="0"
    role="button"
    :aria-labelledby="ariaLabelledby"
    :aria-placeholder="ariaPlaceholder"
    :aria-describedby="`${el$.fieldId}-file-description`"
    @keyup="handleKeyup"
  >
    <span :id="`${el$.fieldId}-file-description`" :class="classes.assistiveText" aria-hidden="">{{ form$.translations.vueform.a11y.file.description }}</span>

    <div :class="classes.wrapper">
      <div :class="classes.file">
        <!-- Filename -->
        <a :href="link" v-if="hasLink && clickable" :class="classes.filenameLink" target="_blank" rel="nofollow noopener">{{ filename }}</a>
        <span v-else :class="classes.filenameStatic">{{ filename }}</span>
      </div>
      
      <div :class="classes.actions">
        <!-- Remove -->
        <div
          v-if="canRemove"
          :class="classes.remove"
          @click.prevent="remove"
          @keypress.enter.space="remove"
          aria-roledescription="❎"
          role="button"
          tabindex="0"
        >
          <span :class="classes.removeIcon"></span>
        </div>

        <!-- Progress -->
        <div v-if="uploading" :class="classes.percent">{{ progress }}%</div>

        <!-- Error -->
        <span v-if="hasError" :class="classes.warning">
          <span :class="classes.warningIcon"></span>
        </span>

        <!-- Upload button -->
        <div
          v-if="canUploadTemp"
          :class="classes.upload"
          @click.prevent="upload"
          tabindex="-1"
        >{{ uploadText }}</div>

        <!-- Success -->
        <span v-else-if="el$.stage > 1" :class="classes.uploaded">
          <span :class="classes.uploadedIcon"></span>
        </span>
      </div>
    </div>

    <!-- PDF preview -->
    <div :class="classes.pdf_container">
      <embed :src="preview" :class="classes.pdf" />
    </div>

    <!-- Upload progress -->
    <div v-if="uploading" :class="classes.progressBar">
      <div :class="classes.progress" :style="{ width: progress + '%' }"></div>
    </div>
  </div>
</template>

<script>
import vueformTheme from '@vueform/vueform/dist/vueform'

export default {
  name: 'FilePreview_pdf',
  data() {
    return {
      merge: false,
      defaultClasses: {
        // Insert default classes
        ...vueformTheme.templates.FilePreview.data().defaultClasses,

        // Add pdf classes
        pdf_container: 'vf-file-preview-pdf-container',
        pdf: 'vf-file-preview-pdf',
      }
    }
  }
}
</script>

<style>
.vf-file-preview-pdf-container {
  margin: 1rem 0;
}

.vf-file-preview-pdf {
  width: 100%;
  height: 500px;
}
</style>

Changes made:

  • we added a container and <embed> for the PDF preview
  • we used the preview prop that contains our File object or the full path to the uploaded PDF
  • we renamed the component to FilePreview_pdf
  • we imported tailwind / vueform theme and copied FilePreview's default classes
  • we added classes for our PDF preview
  • we added <style> block with classes (Vueform Theme only)

The next step is to register the pdf view in vueform.config.js:

js
// vueform.config.js

import { defineConfig } from '@vueform/vueform'
import FilePreview_pdf from './FilePreview_pdf.vue'

export default defineConfig({
  templates: {
    FilePreview_pdf,
  }
})

Once registered we can use it the following way:

vue
<FileElement
  view="pdf"
  accept="application/pdf"
/>
  
👋 Hire Vueform team for form customizations and developmentLearn more