DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Trending

  • Operational Principles, Architecture, Benefits, and Limitations of Artificial Intelligence Large Language Models
  • Data Quality: A Novel Perspective for 2025
  • Orchestrating Microservices with Dapr: A Unified Approach
  • Analyzing Techniques to Provision Access via IDAM Models During Emergency and Disaster Response

Using the PDF Embed API With Vue.js

Getting more control of PDF experiences in the browser.

By 
Raymond Camden user avatar
Raymond Camden
·
Updated Apr. 14, 22 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
13.3K Views

Join the DZone community and get the full member experience.

Join For Free

I've recently become acquainted with Adobe's PDF Embed API. As you can probably guess by the name, it's a library for embedded PDFs on a web page. It is not just a simple viewer; it has APIs for interacting with the PDF and excellent mobile support. This is a part of the Document Cloud service that provides other PDF tools (extraction, conversion, and so forth). I've been playing with the viewer a bit and wanted to see what Vue.js integration would look like. Here's my solution, but note that I'm still learning about the product, so it could probably be done better.

First off, to use the API, you need a key. Clicking the link from the webpage will walk you through generating a key. One important note on this, though. You have to lock down your key to a domain, and that domain cannot be changed either. Also, you can only specify one domain. So, if you want your domain and localhost, create two projects, generate two keys, and set them as environment variables for your development and production environment. I did my testing on CodePen and had to use this domain: cdpn.io

Once you have a key, you can copy the code from the Getting Started to test quickly. Here it is in its entirety, as it's pretty short:

JavaScript
 
<!--Get the samples from https://www.adobe.com/go/pdfembedapi_samples-->

<!DOCTYPE html>

<html>

<head>

 <title>Adobe Document Services PDF Embed API Sample</title>

 <meta charset="utf-8"/>

 <meta data-fr-http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>

 <meta id="viewport" name="viewport" content="width=device-width, initial-scale=1"/>

</head>

<body style="margin: 0px">

 <div id="adobe-dc-view"></div>

 

 

</body>
</html>

Breaking this down, you listen for an event signifying that the library is loaded and then create a new "view" based on a div in your HTML. (In the example above, adobe-dc-view.) Once that's done, you can use the previewFile method to add the PDF viewer to the page. Here's a screenshot of this particular example:

                                                              Figure 1 Screenshot of example


I realize that the screenshot is small, but if you can't see it, the viewer includes the tools you would typically expect in Acrobat - navigation, search, and annotation tools. You can even save directly from the viewer and include your annotations. Here is my attempt at making life insurance documents more fun.

                                                                  Figure 2 Example of Document

Cool. So as I said, it's a pretty powerful embedded viewer, and I want to play with it more later, but I first tried to add it to a simple Vue.js application. Here's how I did it.

First off, notice in the code listing above that we listen for an event on the document object, adobe_dc_view_sdk.ready. For my code to work in Vue, I needed something more robust. An Adobian on the support forum noted that you could check for the window.AdobeDC to see if the library is ready. I wrote my code such that the created method of my Vue app can check that and still handle the library being loaded library. Broadly I did it by using a variable, pdfAPIReady. My created method does this: 

 
JavaScript
 

1
created() {
2
    //credit: https://community.adobe.com/t5/document-services-apis/adobe-dc-view-sdk-ready/m-p/11648022#M948
3
    if(window.AdobeDC) this.pdfAPIReady = true;
4
}, 

And the final bit is a listener outside my Vue application. Remember that you can access the data variable using the Vue instance. This is how I handled that: 

JavaScript
 
// In theory I'm not needed on CodePen, but in the real world I would be.
document.addEventListener("adobe_dc_view_sdk.ready", () => { app.pdfAPIReady = true; });

In theory, my Vue app can make use of the library. The Adobe docs describe how to use local file content driven by an HTML input tag. Basically, you can pass a FileReader promise to the embed, and it will handle knowing when the local file is read and then rendered.

Here's the HTML I used for my demo:

HTML
 
<div id="app" v-cloak>

  <strong>Select a PDF to Preview</strong> 
  <input type="file" accept="application/pdf" @change="previewPDF" ref="fileInput"> 

  <h3 v-if="pdfSelected">PDF Preview:</h3>
  <div id="pdf-view"></div>
  
</div>

Notice the pdfSelected conditional. This is going to toggle after the user has selected a file. I originally had this in a div around the h3 and the div (pdf-view), but the embed viewer didn't like its div being hidden by Vue. (I could probably change how I hide the div, but I'm leaving it for now.) Now for the JavaScript: 

JavaScript
 
const ADOBE_KEY = 'b9151e8d6a0b4d798e0f8d7950efea91';

const app = new Vue({
  el:'#app',
  data:{
    pdfAPIReady:false,
    adobeDCView:null,
    pdfSelected:false
  }, 
  created() {
    //credit: https://community.adobe.com/t5/document-services-apis/adobe-dc-view-sdk-ready/m-p/11648022#M948
    if(window.AdobeDC) this.pdfAPIReady = true;
  }, 
  methods: {
    previewPDF() {
      let files = this.$refs.fileInput.files;
      if(files.length === 0) return;
      this.pdfSelected = true;
      let reader = new FileReader();
      let viewer = this.adobeDCView;
      console.log(`going to view ${files[0].name}`);
      reader.onloadend = function(e) {
        let filePromise = Promise.resolve(e.target.result);
        viewer.previewFile({
          content: { promise: filePromise }, 
          metaData: { fileName: files[0].name }
        });
      };
      reader.readAsArrayBuffer(files[0]);
 
    }
  },
  watch: {
    pdfAPIReady(val) {
      // should only be called when true, but be sure
      if(val) {
        this.adobeDCView = new AdobeDC.View({
          clientId: ADOBE_KEY, 
          divId: "pdf-view"
        });
      }
    }
  }
})

// In theory I'm not needed on CodePen, but in the real world I would be.
document.addEventListener("adobe_dc_view_sdk.ready", () => { app.pdfAPIReady = true; });

For the most part, all I did was use Adobe's example of reading a file and moving it inside a Vue method. The result lets you select a local PDF and have it rendered on my Vue app: 

                                                                        Figure 3 Example of a PDF


This is a relatively straightforward integration but hopefully helpful to folks wanting to use it with Vue. I've got some more examples coming! You can find the complete source code below. 

 
const ADOBE_KEY = 'b9151e8d6a0b4d798e0f8d7950efea91';

const app = new Vue({
  el:'#app',
  data:{
    pdfAPIReady:false,
    adobeDCView:null,
    pdfSelected:false
  }, 
  created() {
    //credit: https://community.adobe.com/t5/document-services-apis/adobe-dc-view-sdk-ready/m-p/11648022#M948
    if(window.AdobeDC) this.pdfAPIReady = true;
  }, 
  methods: {
    previewPDF() {
      console.log("lets do this!");
      let files = this.$refs.fileInput.files;
      if(files.length === 0) return;
      this.pdfSelected = true;
      let reader = new FileReader();
      let viewer = this.adobeDCView;
      console.log(`going to view ${files[0].name}`);
      reader.onloadend = function(e) {
        let filePromise = Promise.resolve(e.target.result);
        viewer.previewFile({
          content: { promise: filePromise }, 
          metaData: { fileName: files[0].name }
        });
      };
      reader.readAsArrayBuffer(files[0]);
 
    }
  },
  watch: {
    pdfAPIReady(val) {
      // should only be called when true, but be sure
      if(val) {
        this.adobeDCView = new AdobeDC.View({
          clientId: ADOBE_KEY, 
          divId: "pdf-view"
        });
      }
    }
  }
})

// In theory I'm not needed on CodePen, but in the real world I would be.
document.addEventListener("adobe_dc_view_sdk.ready", () => { app.pdfAPIReady = true; });

/*
adobeDCView.previewFile({
  content: {
    location: {url: "https://documentcloud.adobe.com/view-sdk-demo/PDFs/Bodea Brochure.pdf"}},
    metaData: {fileName: "Bodea Brochure.pdf"}
});
*/


Published at DZone with permission of Raymond Camden, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!