Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filled form field is invisible/blank, until clicked on. #569

Closed
Sjoerd82 opened this issue Aug 17, 2020 · 10 comments
Closed

Filled form field is invisible/blank, until clicked on. #569

Sjoerd82 opened this issue Aug 17, 2020 · 10 comments

Comments

@Sjoerd82
Copy link

I've implemented the example (zip v3) from #205, but strangely the field values in the output text are invisible until clicked on. Might be related to #488 ?.

I tried to do: acroField.set(PDFName.of('V'), PDFHexString.fromText(text.toString()));
Instead of: acroField.set(PDFName.of('V'), PDFString.of(text));

Also tried to not do this:
acroField.set(PDFName.of('Ff'), PDFNumber.of(
1 << 0 // Read Only
|
1 << 12 // Multiline
));

I really don't know much about PDF, and have no idea where to look. I hope it's something silly, because pdf-lib seems to be a real gem, and I'd hope to integrate it into my project.

Attached is an example. When you click on the character name field (top left, large field), a name appears. Same with the "race:" field. But again, only when you click on the field. When you edit the text and save it in Acrobat reader, the text remains visible.

filled.pdf

@Sjoerd82
Copy link
Author

Fixed by doing: acroForm.set(PDFName.of('NeedAppearances'), PDFBool.True); (thanks to #459 for pointing me in that direction!)

@Graig123git
Copy link

@Sjoerd82 i am having the same issue here is my code const formUrl = 'XXXXX';
const formPdfBytes = await fetch(formUrl).then((res) => res.arrayBuffer());
const pdfDoc = await PDFDocument.load(formPdfBytes);

	const form = pdfDoc.getForm();
	form.set(PDFName.of('NeedAppearances'), PDFBool.True);
	const fields = form.getFields();
	fields.forEach((field) => {
		let type = field.constructor.name;
		let name = field.getName();
		console.info(type, name);
	});
	const nameField = form.getTextField('booked pieces');
	nameField.setText('12');
	const pdfBytes = await pdfDoc.save({ updateFieldAppearances: false });

setting NeedAppearances does not work am i setting this the correct place ?

@Sjoerd82
Copy link
Author

Sjoerd82 commented Oct 9, 2020

I believe so. I noticed that you will pretty much always get this "issue" when you have fields in your PDF that have the same field name... or even worse, at some point in the past had the same field name. I'm using Nitro PDF (an amazing PDF editor by the way - no affiliation), could be related to the editor. If you don't have too many fields, you could try to recreate the fields and taking care not to use the same field name anywhere. PDF's turn out to be a bit finicky, in my personal experience.

@Graig123git
Copy link

@Sjoerd82 i did a console log of all the field names and they are all unique so am not sure at this point

@Hopding
Copy link
Owner

Hopding commented Oct 9, 2020

@Graig123git The reason your fields are blank is because you turned off field appearance updates by setting updateFieldAppearances: false.

@Graig123git
Copy link

@Hopding thanks for that if i remove updateFieldAppearances: false on my form i have a pdf signature that is throwing
the following error Error: Method PDFSignature.needsAppearancesUpdate() not implemented. I have tried disabling this field by setting required to false but still i am getting the error.

@Hopding
Copy link
Owner

Hopding commented Oct 9, 2020

Tracking this in #625

@hjjerrychen
Copy link

The threads above are a bit unclear so for anyone having this issue, you need to add the NeedAppearances line AFTER your entire form has been filled out:

// make sure you import everything required
import { PDFDocument, PDFName, PDFBool } from 'pdf-lib'

const pdfDocument = await PDFDocument.load(...)
...
// some code to fill out your form
...
pdfDocument.getForm().acroForm.dict.set(PDFName.of('NeedAppearances'), PDFBool.True)

where pdfDocument is the document you loaded or created with PDFDocument.load(), PDFDocument.create() or with some other method in PDFDocument.

Acrobat, unlike other PDF readers, only generate appearance streams when it is explicitly told to do so, by setting /NeedsAppearances to true in the AcroForm dictionary. This is usually preserved when you fill out a single form, but when you copy forms, the setting is lost. More discussion can be found and credits goes to: gettalong/hexapdf#86 (comment)

@conor909
Copy link

conor909 commented May 22, 2022

@jerry70450 thanks! This helped me solve the invisible text issue, although by doing so my images dont appear as they did before I set NeedAppearances. Would this have effected other fields / buttons? I'm adding images as follows:

const pathToLogo = path.join(__dirname, '../images/my-logo.png')
const logoImgBytes = fs.readFileSync(pathToLogo).buffer
const logoImage = await page.embedPng(logoImgBytes)
const logoPlacement = form.getButton('logo')
logoPlacement.setImage(logoImage)

@glimmbo
Copy link

glimmbo commented Jul 26, 2022

Caveat with this solution (as with everything pdf/Adobe related), the fields will not show in Mac's Preview.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants