How can I implement pdfjs in liveview?

How can I exactly implement pdfjs in elixir liveview?

1 Like

You’ll need to create a Hook: JavaScript interoperability — Phoenix LiveView v0.18.3


Please provide a practical example/guide

What have you tried so far? Have you got pdfjs working without liveview?

1 Like

I have installed pdfjs using npm, I have made a template and created a hook in app.js.
At template


<div id="pdfReader"></div>
<canvas id="myreader"></canvas>

At app.js

import Hooks from "./hooks";

At hooks.js

import pdfReader from "./hooks/pdf";

let Hooks = {
    pdfReader: pdfReader

export default Hooks;

At pdf.js

import pdfjsLib from "pdfjs"
const pdfReader = nameRoute => {           
    let loadingTask = pdfjsLib.getDocument(nameRoute),
        pdfDoc = null,
        canvas = document.querySelector('#cnv'),
        ctx = canvas.getContext('2d'),
        scale = 1.5,
        numPage = 1;

        const GeneratePDF = numPage => {

            pdfDoc.getPage(numPage).then(page => {

                let viewport = page.getViewport({ scale: scale });
                    canvas.height = viewport.height;
                    canvas.width = viewport.width;
                let renderContext = {
                    canvasContext : ctx,
                    viewport:  viewport

            document.querySelector('#npages').innerHTML = numPage;

        loadingTask.promise.then(pdfDoc_ => {
            pdfDoc = pdfDoc_;
            document.querySelector('#npages').innerHTML = pdfDoc.numPages;

const startPdf = () => {

window.addEventListener('load', startPdf);
export default pdfReader;

But still no working

Anyone wishing to help might first want to look through this discussion of the same problem on the Elixir Discord to prevent double work and outdated code examples: Discord

Here’s a working example from my project:

To install JS dependency: npm install pdfjs-dist



It has simple pagination and zoom controls. It’s a bit hacky and the JS is messy but hopefully it can help others get started…


Very useful example!

Just some relevant feedback with running Purple locally.

Initially, I copied the secrets.exs.sample to secrets.exs without adding any details.

Then, I could not find any functionality for signing in a new user (just logging in an existing one). I did a “hack” by copy-pasting in the Postgres repo account (in the users table) the credentials from another repo of mine that is “compatible” with yours.

Additionally, an error was thrown in Purple.Uploads.get_file_info/2 (line 40). I “hacked” this again by merely returning %{extension: ".pdf"} (I skipped using Mogrify.identify/1 that raised the error).

Then everything worked like a charm! The pdf can be viewed in the Liveview.

Thank you for sharing this.

Oh nice haha, I wasn’t expecting anyone to actually try running it. I create accounts from IEX, and Mogrify requires imagemagick to be installed locally. Glad it could help, cheers!

1 Like

I have also tested it. Working well. I have referenced the code and added the hook at app.js and also added the pdf.js file. My liveview has this


where by an example of book_path is ""/home/peter/Documents/2work/uploads/23-Learning Web Design _ A Beginner’s Guide to HTML, CSS, JavaScript, and Web Graphics ( PDFDrive ).pdf" ". But am getting missing pdf error in browser console. I can see it added http://localhost which is unintended.
Please help.
@knoebber @bdarla
` Check attached photo

Even if I hardcode the pdf_path to an online one like this, still not working.
@knoebber @bdarla @Nicd

I would suggest studying in more details @knoebber’s project, especially if you plan to implement this functionality in a new project of your own.

There are some files that hold features related with uploading, e.g. in the config directory.

Moreover, it is important to understand that @knoebber’s project involves a controller (FileController) that responds to the request of the hook for the pdf file.

Of great importance is also the router.ex that comprises the routes to the aforementioned controller.

Finally managed to refactor the code. Its working very well. The problem is that its not working on small screens such as phones.
@knoebber @bdarla

Hi - it works fine on my phone for me (iphone 12). I can try to help out if you ask a more specific question.

How can I enable input to a particular page and viewing of page numbers? As attached

Plus showing percentage of zoom

It might be that for touch-screen based input, the javascript has to be configured to capture “touch” events, in addition to the corresponding “click” events.

Hi - I don’t feel like implementing that UI right now. It’s certainly possible though. You’ll have to extend the JavaScript hook that I provided with additional calls to the pdfjs API.

Check the implementation of pdfjs for more info: GitHub - mozilla/pdf.js: PDF Reader in JavaScript

@knoebber @Nicd
Managed to diplay page number. I just added
At pdfJS
var myDiv = document.getElementById('special'); myDiv.innerHTML = currentPageNum;
At liveview

<div id="special" class="">

It works very well. Same can be replicated to get total pages by replacing currentPageNum with pdf.numPages.

The next thing is allowing scrolling. Anybody who can implement that??