How do I delete a PDF field?

75 views
Skip to first unread message

André Rieussec

unread,
May 2, 2018, 1:01:15 PM5/2/18
to PDFTron WebViewer
Hi,

I posted this as a question in a previous thread but I figured it would be more useful for others if it was its own thread.

When I load a PDF document which has fields into the WebViewer, it appears that PDFNetJS will create annotation for the fields. I can access them using:

annotManager.getAnnotationsList();

I can then delete the annotation using:
annotManager.deleteAnnotation();

And it appears the field is gone. However if I save the PDF to the server and load it back, the field is back again. So I think only the annotation was removed but not the underlying field. I looked around the API docs but didn't see anything that would let me delete the actual field. Is there a way to do that?

Thanks!

Matt Parizeau

unread,
May 2, 2018, 6:17:32 PM5/2/18
to PDFTron WebViewer
Hi André,

Currently PDFNetJS (and PDFNet) don't directly support the deleting of form fields from the document when importing XFDF. What you could do is keep track of the widget annotations that you delete on client side and then pass that information to your server and run PDFNet code to delete the specific fields.

For example on the client keep an array of deletedWidgets and push to it before deleting:
deletedWidgets.push({
  name
: widget.fieldName,
  widgetIndex
: getWidgetIndex(widget)
});
annotManager
.deleteAnnotation(widget);

The getWidgetIndex function would look like:
function getWidgetIndex(widget) {
 
var field = widget.getField();
 
var widgetIndex = 0;
 
for (var i = 0; i < field.widgets.length; ++i) {
   
if (field.widgets[i] === widget) {
      widgetIndex
= i;
     
break;
   
}
 
}
 
return widgetIndex;
}

Then on the server use the deleted widget information:
std::vector < std::pair < UString, int > > toDelete;
// use your own data here, but here is an example
toDelete
.push_back(std::pair < UString, int > (UString("Radio Button1"), 2));
toDelete
.push_back(std::pair < UString, int > (UString("Check Box1"), 0));

for (UInt32 i = 0; i < toDelete.size(); ++i) {
  std
::pair < UString, int > currentOperation = toDelete[i];
 
UString field_name_ustr = currentOperation.first;
  std
::string field_name = field_name_ustr.ConvertToUtf8();
 
FieldIterator itr = doc.GetFieldIterator(field_name_ustr);
 
if (itr.HasNext()) {
   
bool still_valid = true;
   
for (int i = 0; i < currentOperation.second; ++i) {

      itr
.Next();
     
if (!itr.HasNext() || itr.Current().GetName() != field_name_ustr) {
        still_valid
= false;
       
break;
     
}
   
}

   
if (still_valid) {
     
// find the parent page
     
Field current_field = itr.Current();
     
Page p(current_field.GetSDFObj().FindObj("P"));
      cout
<< "Processing Field " << current_field.GetName() << endl;
     
if (p.IsValid()) {
       
bool annotation_deleted = false;
       
// find the annotation on this page and remove it
       
for (UInt32 i = 0; i < p.GetNumAnnots(); ++i) {
         
if (p.GetAnnot(i).GetSDFObj() == current_field.GetSDFObj()) {
           
// delete the annotation
            p
.AnnotRemove(i);
            annotation_deleted
= true;
         
}
       
}
       
if (!annotation_deleted) {
          cerr
<< "Could not find Widget with field name " << field_name << " in the parent page" << endl;
       
} else {
          cout
<< "Successfully deleted Widget with field name " << field_name << endl;
       
}
     
} else {
        cerr
<< "Required key P (the page reference) is missing" << endl;
     
}
   
} else {
      cerr
<< "Could not find Widget with field name " << field_name << " at index " << currentOperation.second << endl;
   
}
 
} else {
    cerr
<< "Could not find Widget with field name " << field_name << endl;
 
}
}

Matt Parizeau
Software Developer
PDFTron Systems Inc.
Reply all
Reply to author
Forward
0 new messages