Shared Data in Packages Part 2

Last week I started to outline a design pattern for sharing data in a package.  Again, the general problem we’re trying to solve is to allow multiple forms in a PDF package exchange data — where fields common to multiple forms is propagated.  Part 1 of the problem is establishing a communication mechanism between documents.  Once the documents have been disclosed to each other, any document in the package can modify any other document.  Today’s Part 2 entry describes how to do the sharing.

Data mapping strategies

Implementing data sharing means solving a mapping problem: How do we know which fields in one PDF correlate to which fields in other PDFs? There are several techniques we could choose, including:

  1. Use the same name for common fields
  2. Generate a manifest that explicitly correlates fields
  3. Base all forms in the package on a common data schema

For my solution, I’ve chosen the 3rd option: common schema.  The underlying assumptions are:

  • Field values get propagated by assigning values in the data dom — a data value from one form will have the same data node address in each of the other forms
  • The data dom in the package document will hold the aggregate data of all forms in the package — this is the ‘master copy’ of the data.  Note that the package document does not have to have fields correlating to all the data elements.
  • Attached forms will have their data synchronized from the master copy of the data when they are launched in Reader

Data Sharing Algorithm

With these assumptions in place, the actual algorithm is fairly simple:

  1. When any attachment opens, it registers with the package document
    (the topic of Part 1)
  2. At registration, all data values of the attachment are synchronized from the master copy of the data in the package
  3. While the attachments are open, detect when field values change.  The technique used to detect field value changes is to use propagating enter/exit events. We save the field value at field enter, and compare it to the result at field exit. 
  4. When a field value changes, send a synchronize message to the package document.
  5. When the package document gets a synchronizing message, it updates the master copy of the data and then propagates the change to all other open attached PDFs.

One benefit of this approach is that the actual logic used to synchronize the data resides in the package document. This means you can customize your data sharing algorithm by modifying only the script in the package.

Design Experience

The really good news is that you can put this all together in a very simple design experience.  With today’s sample, there are two fragment subforms: packageSync and embeddedSync. You can probably figure out where they each go.  The fragment subforms have all the logic needed to register and synchronize the documents.  They contain propagating enter/exit events so that all fields in the form are automatically synchronized.  So the Design experience is as simple as:

  1. Drag the packageSync fragment on to a package subform
  2. Drag the embeddedSync fragment on each each attachment form
  3. Attach the embedded forms to the package form

Global Submit

Since the package document holds the aggregate of all the data, a global submit operation can be achieved by simply submitting the data from the package document.

Limits

There are some limits to the synchronization that you should be aware of:

  • No handling for complex field value: rich text, images, multi-select choice lists
  • Does not synchronize subform occurrences
  • Does not synchronize calculated values
  • Because we are relying on propagating events, the solution works only in Reader 9.1 or later

Each of these problems are solvable. I was just too lazy.

The Sample

The sample form and all fragments are in this zip file. Try opening PackageSample.pdf and one or both attachments.  Fill in fields and observe that they get propagated.  Note that any field that has focus will not get updated until you exit the field.

9 Responses to Shared Data in Packages Part 2

  1. Bibhu says:

    Hello John,

    I am using a sample XML to embed the data in a form. Lets say I have a dropdown where the XML is embede.When the user selects one choice from the dropdown and send the form as xml , all the embedded xml data comes.How can I get only the selected choice from the dropdown as xml instead of getting all the xml that’s embeded.

    Thanks.

    Bibhu.

  2. Bibhu:
    I’m not sure I get your scenario exactly. Are you using dynamic binding to populate your list box options from xml data? If so, there are several options available:
    1. use xslt to transform your data as it is submitted to remove the extra data
    2. use the acroform submitForm() api to submit modified data
    3. use a preSubmit event to remove the unwanted data, and a postSubmit event to put it back
    Of these options, likely #3 is the easiest to implement.

    John

  3. Bibhu says:

    Hello John,

    Thanks for the reply. Sorry am a bit late to respond. Could you please suggest or give an example to how to implement the option 3. Would the pre submit even work in Adobe Reader 8 ?As I am not an expert in applying the XSLT so this is not an option for me. I would like to stick with option 3. Please suggest.

    Thanks.

    Bibhu.

  4. Bibhu says:

    John,

    Sorry !! I forgot to mention one thing. Yes, I am using dynamic property to update the fields basing on the selections made in one field. I am using some hidden dropdown lists as LiveCycle allows us to update only one field basing on one field.

    Thanks.

    Bibhu.

    • Bibhu:
      I don’t know what LiveCycle restriction you’re referring to. Sounds suspicious. Regardless, Here’s a script object that should do what you want:

      form1.#subform[0].#variables[0].saveRestore – (JavaScript, client)
      var saveData;
      var saveParent;
      function save(nodeName) {
      saveData = xfa.datasets.data.resolveNode(“$..” + nodeName);
      saveParent = saveData.parent;
      saveParent.nodes.remove(saveData);
      }
      function restore() {
      saveParent.nodes.append(saveData);
      saveParent = saveData = null;
      }

      If the data node that you want to exclude is called “F2”, then the presubmit script is:
      saveRestore.save(“F2”);
      and the postsubmit script is:
      saveRestore.restore()

      AFAIK it works in reader 8.

      good luck.

      John

  5. Bibhu says:

    Hello John,

    Thanks for the reply. The restriction I meant to say is : For example you have an ItemSection. Where you have ItemNumber (DropDown) ,ItemTitle(TextField), ItemPrice
    (TextField).

    Using dynamic property we can set the value of ItemTitle and text as ItemTitle while binding the ItemNumber Dropdown.

    But If we want to update the ItemTitle and ItemPrice simultaneously then what will we do ?? Can we update more than one field using dynamic property ? That’s why I have used hidden fields.

    My form has basically two sections. 1. CustomerSection. 2.ItemSection. ItemSection spans over 3 and half pages. Total no.of customer nodes present is 157 and total no.of Item nodes present are about 500.

    Requirement : As there are so many no.of items so it would create a autosuggest box when you type some character in the required field.

    After completeting the form the user should send it as PDF to the admin. The Admin will made some corrections/updation into the form.After that they will update their DB.

    My Questions is If I will trim the nodes and would send only one node how this auo-suggest dropdown will work at the admin’s end ??

    Could you suggest some way where the admin can update their DB after making some corrections to the form where only the form data will go as xml ?

    Thanks.

    Bibhu.

    • Bibhu:
      Roughly speaking, in your scenario you have meta data (the descriptive values and drop down contents) and you have data (the values of the fields filled in by the user).
      When you use dynamic binding with your meta data there’s no problem with binding multiple field properties from the same piece of meta data. That should work fine.
      But if dynamic binding isn’t an easy fit, there’s no problem with using calculations instead.
      I wouldn’t recommend binding hidden fields to the meta data. I’d recommend that the calculations reference the data directly from the data dom. e.g. you could put a calculation on a subform to assign the form properties from the meta data.
      As for the rest of your workflow — if the meta data is needed to provide the proper form experience, then clearly your can’t strip it out before you get to the admin stage. Maybe you need two different actions — submit by the originating author (doesn’t strip meta data) and submit by the admin (does strip meta data).
      As for ways to update a DB from XML — a typical LiveCycle customer would do this on the server where there are lots of tools available. You might want to consider hosting the form in Acrobat.com where you get some nice data aggregation possibilities.

      John

  6. Bibhu says:

    Hello John,

    Thanks for the reply. Could you please post a sample where more than one field values are getting updated by the use of calculation script. What would be the problem if I would use hidden fields to update the values. It’s working fine here.

    So, what should be the final solution here ??

    Thanks.

    Bibhu.

    • Bibhu:
      Regretfully, I can’t spend more time on this topic. These are fairly standard design problems, probably best to look for help in the forums.

      Good luck.

      John