Stefan Cameron on Forms
Building intelligent forms using Adobe LiveCycle Designer

Remove, Remerge

There’s a bug currently logged against Acrobat 7.x where removing an instance of a dynamic subform, using the Instance Manager (IM)’s removeInstance(int) method, doesn’t cause an update to the IM’s count of currently instantiated subforms.

OK, so maybe that was a little too technical so I’ll try to simplify: In Acrobat 7.x, when you remove an instance of a dynamic subform using the IM’s removeInstance(int) method and then check the number of remaining instances using the count property, the number you’ll get won’t reflect the number that remains.

Adobe is aware of this bug and will hopefully be providing a fix for it in an up-coming release.

Fortunately, there’s a simple work-around (and even if the bug gets fixed in a future release, you should probably be checking the version of Acrobat that’s running your form to determine whether you need to be using the work-around or not):

_DynamicSubformInstanceManager.removeInstance(3);

// Force a remerge of the form's current data set with its template
//  to cause an update to the "count" property of all IMs
xfa.form.remerge();

Calling the Form object’s remerge() method will “force the remerging of the data model and template model to re-create the form model”, as explained in the Adobe XML Form Object Model Reference. This means that the form’s current data set will be remerged with the template (the form objects like dynamic subforms, fields, etc.). The result will be a form that looks exactly the same as it did in its state just prior to calling xfa.form.remerge() but with all IMs properly updated to the current number of dynamic subforms which they’re managing, thus correctly updating each IM’s count property.

Even if this problem is addressed in a future release, you’ll want to check the version of Acrobat that’s running your form in order to know whether it has the fix or not (in JavaScript as follows):

// get the host's version as a string and split it into an array
var oVerArray = xfa.host.version.split(".");

if (oVerArray[0] == "7")
  xfa.form.remerge();

Or more simply:

if (xfa.host.version.split(".")[0] == "7")
  xfa.form.remerge();

Posted by Stefan Cameron on May 25th, 2006
Filed under Instance Manager,Scripting
Both comments and pings are currently closed.

8 Responses to “Remove, Remerge”

  1. sergio on July 6th, 2007

    Hello Stefan,

    I would like to get some comments from you about the problematic of adding and removing instances from a form. In your tutorial, there are some references to the necessity of making a relayout of the layout of the form so that one can add and remove instances correctly. This seems to be a 7.0 designer issue.

    However, I´m now using designer 8.1 and it seems that sometimes one can´t add/remove the right instance, even if we make a relayout of the form. The problem is that I need to add/remove instances between instances, and today, I´m not sure I will can do it without “bugs”: after playing around a little bit with a form like this, it seems acrobat will gets “confused”. In this case, when I add a new instance, the new instance will have 2 buttons (one to remove the instance itself and other to add a new instance right after it), so in fact it is a confusing mechanism… but I need it, and it should works…

    (note: this can be more complicates, because one of the instances must have a dinamcally table (columns and rows added dinamically)

    Thank you

  2. Stefan Cameron on July 15th, 2007

    sergio,

    The issues with adding and removing instances actually lie with the version of Acrobat you’re using, not Designer. You say you’re now using Designer 8.1: Does that mean that you’re using Acrobat 8.1 as well? Or do you need to target an earlier version of Acrobat?

    When you remove an instance, you should be using the ‘s “removeInstance(index)” method, where “index” is the zero-based index of the instance you wish to remove. You can find this index easily by using an object’s “parent” property to find the instance subform that contains a “delete” button and then use that subform’s index property as the value you supply to the “removeInstance” method. For example, if you “delete instance” button is a direct child of the instance subform, you could use this JavaScript:

    this.parent.parent._DynamicSubform.removeInstance(this.parent.index);

    As for inserting an instance immediately after the one containing the “add” button that was clicked, if you’re targeting Acrobat 8.0 or later, you can use the “insertInstance(index)” method along with the index property of the subform instance in order to insert an instance into the set rather than using “addInstance” to append a new instance at the end and then using “moveInstance” to get it into the right position. (Don’t forget to add 1 to the subform instance’s index in order to get the new instance inserted after the existing one.)

    Note that “insertInstance” is only available in Acrobat 8.0 or later.

  3. Meng on September 4th, 2007

    Hi Stefan,

    For your information I have created a dynamic tables with section which can expand on demand.
    The structure is as following:

    Table
    – Section
    – Row1
    – Row2

    Row1 is for “Milestone” while Row2 is for “Deliverables”. So you can see that for every Milestone there can be more than one deliverable row. I have made the section and row2 repeatable thus I can get the desired outcome, that I can add any number of Row2 underneath the corresponding Row1 on the fly.

    It works great but the problem occurs when I try to use xfa.form.remerge(). The order of the rows changed after the method call.

    While trying to figure out the problem, I have discovered that index for every Row2 will be “counted” regardless that I have inserted under different Row1. If I have 2 Row2 for Row1 then the next index for Row2 for the second Row1 would be 2 instead of 0.

    To make it clear, I have come out with these scenarios.

    Before remerge():

    Table
    – Section
    – Row1[0]
    – Row2[0]
    – Row2[1]
    – Row2[2]
    – Row1[1]
    – Row2[3]
    – Row2[4]

    After remerge():

    Table
    – Section
    – Row1[0]
    – Row1[1]
    – Row2[0]
    – Row2[1]
    – Row2[2]
    – Row2[3]
    – Row2[4]

    And as you can see the graphical outcome is that all the Row2 rows appear below the last Row1 row. This is actually not what I want at all.

    So, do you have any idea how could I deal with this problem? Or may be I have misused the way Table Section works?

    Thanks in advance.

  4. Stefan Cameron on September 21st, 2007

    Meng,

    I think you’re seeing this behaviour because you’re attempting to use a table section to contain the instances of the Row2 row. A table section is essentially a subformSet object which is designed to contain many subforms (rows in a table) but in a specific order, that order being “document order” (or the order in which they are defined in the Hierarchy palette). When you remerge the form, the result is that the rows within the table section get re-ordered to match the document order as opposed to the order in which you specified them by adding instances.

    To get around this, I would suggest you create a table with a single row (call it “section”) and within that row, insert a nested table with two rows (“row1” and “row2” for the milestone and deliverable data). Make the “section” and “row2” rows repeatable. To add a new section, simply add a new instance of the “section” row and then to add a new deliverable, simply add a new instance of the “row2” row in the nested table contained in the “section” row.

  5. Meng on September 25th, 2007

    Hi Stefan,

    Thanks so much for your solution!!!!!
    I have spent few days’ time making a yet perfect workaround using scripts to deal with that but it seems that your solution is superior and much easier.
    May be I should spend more time in mastering the components instead of coding in the future =)

    Once again, thanks a million.

  6. Stefan Cameron on September 25th, 2007

    Meng,

    You’re very welcome. I’m glad I was able to help you out!

  7. nik on November 25th, 2008

    Hi Stefan,

    I manage to create a dynamic table which capable to grow on user demand for the use of company’s internal purchase requisition. It works perfectly, until someday somebody in the management ask me if I can generate Purchase Order based on internal purchase requisition.

    I need to populate the dynamic table in the requisition form to be used in Purchase Order form. My question is, what should I do in order to replicate the same dynamic table without using external application / accessing database. I’m currently using Designer 8.
    Thank you in advance.

  8. Stefan Cameron on November 28th, 2008

    nik,

    Unless you can somehow fit both forms into one single form (which would most likely be more trouble than it’s worth), I think you’re going to need to import some type of data into your purchase order form (that being the data from the requisition form). This is where LiveCycle really shines because it would let you create a workflow process which is initiated by the submission of a requisition form’s data, takes the data and merges it into a purchase order form and sends the purchase order to the vendor (for example).