Hopding / pdf-lib

Create and modify PDF documents in any JavaScript environment
https://pdf-lib.js.org
MIT License
6.6k stars 635 forks source link

Textarea fields only show filled value when they have focus #1584

Closed cloudevolve closed 6 months ago

cloudevolve commented 6 months ago

What were you trying to do?

Using the fillable form methods to fill some data. What I am seeing is when I will a textarea element it is not replacing the text unless you flatten or give focus to the element.

How did you attempt to do it?

Here is the JS using to fill the element: const pdfBytes = new Uint8Array(await result.arrayBuffer());

    const pdfDoc = await PDFLib.PDFDocument.load(pdfBytes);
    const form = pdfDoc.getForm()
    const nameField = form.getTextField('Insert Preparer Name');           
    nameField.setText('My Test');

What actually happened?

image image

What did you expect to happen?

Expected the text to be visible without focus

How can we reproduce the issue?

I can send the document privately if needed

Version

Latest

What environment are you running pdf-lib in?

Browser

Checklist

Additional Notes

No response

drewf7 commented 6 months ago

Just throwing out there in case it's helpful (or for others who find this via google).

I'm dealing with a similar issue. In my case calling textField.updateApperances fixed the issue for most PDF viewers, but not on macs.

I suspect this is related to the comment in PDFDocument.copy https://github.com/Hopding/pdf-lib/blob/93dd36e85aa659a3bca09867d2d8fac172501fbe/src/api/PDFDocument.ts#L747

   * > **NOTE:**  This method won't copy all information over to the new
   * > document (acroforms, outlines, etc...).

After applying text to form fields and then merging that PDFDocument with another, the acroforms are lost, meaning some PDF viewers have trouble with the text in the fields.

EDIT: If you don't need the fields to remain editable, flattening the form before merging PDFs should also work.

drewf7 commented 6 months ago

So I found a way to make this work. I'll give the disclaimer that it's a bit hacky. But my merged PDFs are previewing correctly on all platforms now.

I ended up explicitly copying all the acroFields as part of my copy/merge operations.

So something like the below

let sourceDoc: PDFDocument = <however you loaded your source>;

/** Make your form modifications to sourceDoc here */

await sourceDoc.save(); // I don't know why the save is important but it is
const mergedPDF = await PDFDocument.create();
const copiedPages = await mergedPDF.copyPages(sourceDoc, sourceDoc.getPageIndices());

copiedPages.forEach((page) => {
    mergedPDF.addPage(page);
});

const copyForm = sourceDoc.getForm();
const mergedForm = mergedPDF.getForm();
const fields = copyForm.acroForm.getAllFields();
for (const field of fields) {
    const acroField: PDFAcroField = field[0];
    for (const dictEntry of acroField.dict.entries()) {
        mergedForm.acroForm.dict.set(dictEntry[0], dictEntry[1]);
    }
}

YMMV but wanted to leave this incase it helps.

cloudevolve commented 6 months ago

@drewf7 Thank you Drew, I will certainly give these a shot and let you know how it goes!

cloudevolve commented 6 months ago

@drewf7 Thank you my friend, your solution resolved the issue I was facing. Really appreciate the help!