How to advice - many forms to many instances

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

How to advice - many forms to many instances

Hank Ratzesberger-3
Hi,

Hoping someone can take a few minutes for some feedback on my implementation plan. I'm trying to edit xml documents that have many "things"of many different types.

So I thought, well, I need one form for each type of thing, then when the user wants to edit a particular one of the items, it is copied into the instance bound to the form.  The user edits the item, clicks an update, the form data replaces the "thing" in the main instance.

The other way I suppose, I could do this, is put a form on the row following the description of the change, and make the case relevant. I think I could figure out how to the get the controls to bind to the particular item in the summary row. 

(Well, I think I have decided to go with this later idea, its much more like the Bookcast example.)

Thanks,
Hank




The document I want to edit is for Liquibase, a SQL change control tool:

http://www.liquibase.org/documentation/changes/index.html

--
Hank Ratzesberger
XMLWerks.com

--
You received this message because you are subscribed to the Google Groups "Orbeon Forms" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Reply | Threaded
Open this post in threaded view
|

Re: How to advice - many forms to many instances

Hank Ratzesberger-3
Happy New Year everyone.

I continue to struggle with the best way (is there a design pattern for this?) to take a very complex xml file and present the portions of it that fit into a form. 

Given an xml file that is very random -- it has various elements in any order, and each element requires it's own form to edit, can xforms logic branch in such a way that a form can be built for each of the elements and new ones that are added?

I thought this might be possible by having an instance for each type of change <createTable>, <addColumn>, etc., then copy from the main instance to the one that is bound to the form, but I don't see a way to copy back.

I have just about concluded that it requires xslt on the server which can create the form 'on the fly' that matches the complex xml file.

Any thoughts?  Here is some code:

Thanks,Hank

<!-- example xml -->
<databaseChangeLog>

<changeSet id="changeSet-1" author="hratzesberger">
<createTable tableName="person">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false" />
</column>
<column name="firstname" type="varchar(50)" />
<column name="lastname" type="varchar(50)">
<constraints nullable="false" />
</column>
<column name="state" type="char(2)" />
</createTable>
</changeSet>

<changeSet id="changeSet-2" author="hratzesberger">
<addColumn tableName="person">
<column name="username" type="varchar(8)" />
</addColumn>
</changeSet>

<changeSet id="changeSet-3" author="hratzesberger">
<addLookupTable existingTableName="person"
existingColumnName="state" newTableName="state" newColumnName="id"
newColumnDataType="char(2)" />
</changeSet>

</databaseChangeLog>

<!-- a switch that contains one case for each type of change to make -->
<xf:switch>
   <xf:case id="case-loadData">
      <xf:group>
         <xf:label>loadData</xf:label>
         <xf:input ref="instance('edit-loadData')/@catalogName">
             <xf:label>Catalog Name:</xf:label>
         </xf:input>
         <xf:input ref="instance('edit-loadData')/@schemaName">
             <xf:label>Schema Name:</xf:label>
         </xf:input>
         <xf:input ref="instance('edit-loadData')/@tableName">
             <xf:label>Table Name:</xf:label>
         </xf:input>
         <xf:input ref="instance('edit-loadData')/@file">
             <xf:label>File:</xf:label>
         </xf:input>
     </xf:group>
  </xf:case>
 

<!-- a piece of the code that -->
<xf:repeat nodeset="/databaseChangeLog/changeSet" id="change-sets">
    <xf:var name="thing" value="./child::*"/>
    <xf:trigger>
        <xf:label>Edit</xf:label>
        <xf:action ev:event="DOMActivate">
           <!-- Delete the old value in the the editable instance how? -->
           <xf:delete context="" at="" nodeset=""/>
           <!-- Insert this context into the editable instance of the same name/type -->
           <xf:insert context="instance(concat('edit-',name(child::*))" at="0" origin="$thing"/>
           <!-- toggle the case that edits the data -->
           <xf:toggle case="case-{name(child::*)}"/>
           <!-- now how do I copy back that data to the main instance? -->

 

--
Hank Ratzesberger
XMLWerks.com

--
You received this message because you are subscribed to the Google Groups "Orbeon Forms" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Reply | Threaded
Open this post in threaded view
|

Re: How to advice - many forms to many instances

Hank Ratzesberger-3
In reply to this post by Hank Ratzesberger-3
I thought I would get back to say that I have part of the solution.

Firstly, at the top level of my document, I DO have a list of the same elements.  Otherwise, I'm not sure what XForms would do if you created the repeat <xf:repeat nodeste="*">  to iterate all/any child nodes.  

Instead, I can iterate all the <changeSet> elements
<xf:repeat nodeset="changeSet" id="change-sets">
<xh:tr>
<xh:td>
Within the changeSet is just one type of change, but I don't know what it is, 
so I just put it into a variable, and get it's name:
            <xf:var name="thing" value="*"/>
<xf:var name="nameOf" value="name(*)"/>
<xf:trigger>
<xf:label>Edit</xf:label>
<xf:action ev:event="DOMActivate">
I have an instance for each type which has its own form, e.g. 'edit-changeColumn'
or 'edit-addIndex' etc. I insert my current node into the "editable instance" as
the first node and the bindings still work because they default to the first:
<xf:insert context="instance(concat('edit-',$nameOf))" at="0" origin="$thing"/>
Now the editable instance has two elements, so I need to delete the old one.
                    <xf:delete ref="instance(concat('edit-',$nameOf))/*[2]"/>
Now I can toggle the form.  This works because there is only one case on this page,
and I presume it would break if there were others.

Next, I have to figure out how to replace the node in this repeat with that in the
editable instance.

Cheers,
Hank
                    <xf:toggle case="case-{$nameOf}"/>
</xf:action>
</xf:trigger>




On Tue, Dec 30, 2014 at 1:46 PM, Hank Ratzesberger <[hidden email]> wrote:
Hi,

Hoping someone can take a few minutes for some feedback on my implementation plan. I'm trying to edit xml documents that have many "things"of many different types.
--
Hank Ratzesberger
XMLWerks.com



--
Hank Ratzesberger
XMLWerks.com

--
You received this message because you are subscribed to the Google Groups "Orbeon Forms" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Reply | Threaded
Open this post in threaded view
|

Re: How to advice - many forms to many instances

Alessandro  Vernet
Administrator
Hi Hank,

If I understand the problem, the typical way of doing this is as follows:

<xf:repeat nodeset="changeSet">
      <xf:var name="thing" value="*"/>
      <xf:var name="nameOf" value="name(*)"/>
      <xf:group ref=".[$nameOf = 'createTable']">
          UI elements to edit a "createTable"
      </xf:group>
      <xf:group ref=".[$nameOf = 'addColumn']">
          UI elements to edit a "addColumn"
      </xf:group>
      …
</xf:repeat>

In fact, initially, this is what Form Builder (which is itself using XForms) was doing, with an xf:repeat iterating over the controls in the source of the form you were editing, and then "selecting" which control to show based on the actual control in the XForms source.

Now, in your case, it looks to me like you just want to be able to edit the items when the user clicks on the Edit button. But I didn't get the part of you needing another instance; how is edit-addColumn different from the content of addColumn? Are you doing an insert because you want to keep the original data, in case users press "Cancel" instead of "Save" when editing? But then, why not duplicate <addColumn>?

Alex
--
Follow Orbeon on Twitter: @orbeon
Follow me on Twitter: @avernet
Reply | Threaded
Open this post in threaded view
|

Re: How to advice - many forms to many instances

Hank Ratzesberger-3
Hi Alessandro,


On Mon, Jan 12, 2015 at 6:09 PM, Alessandro  Vernet <[hidden email]> wrote:

> Hi Hank,
>
> If I understand the problem, the typical way of doing this is as follows:
>
> <xf:repeat nodeset="changeSet">
>       <xf:var name="thing" value="*"/>
>       <xf:var name="nameOf" value="name(*)"/>
>       <xf:group ref=".[$nameOf = 'createTable']">
>           UI elements to edit a "createTable"
>       </xf:group>
>       <xf:group ref=".[$nameOf = 'addColumn']">
>           UI elements to edit a "addColumn"
>       </xf:group>
>       …
> </xf:repeat>

hmm, yet it appears to me for each iteration of changeSet, a group
will be created
for each of the two dozen types, though only one will be visible because the ref
will evaluate to relevant. Is that correct? Or is there no overhead because the
creation of the elements happens on the event (xforms-refresh?) ?

> In fact, initially, this is what Form Builder (which is itself using XForms)
> was doing, with an xf:repeat iterating over the controls in the source of
> the form you were editing, and then "selecting" which control to show based
> on the actual control in the XForms source.
>
> Now, in your case, it looks to me like you just want to be able to edit the
> items when the user clicks on the Edit button. But I didn't get the part of
> you needing another instance; how is edit-addColumn different from the
> content of addColumn? Are you doing an insert because you want to keep the
> original data, in case users press "Cancel" instead of "Save" when editing?
> But then, why not duplicate <addColumn>?

The edit-addColumn does indeed edit the same content, it was not clear
to me how display the form based on the type of content, without a lot of
conditional statements.  (There was a small benefit of being able to reset
just the section being edited.)

Thank you, let me think about this and give it a try, it certainly would reduce
the number of instances!

--Hank

>
> Alex
>
>
> -----
> --
> Follow Orbeon on Twitter: @orbeon
> Follow me on Twitter: @avernet
> --
> View this message in context: http://discuss.orbeon.com/How-to-advice-many-forms-to-many-instances-tp4659385p4659421.html
> Sent from the Orbeon Forms community mailing list mailing list archive at Nabble.com.
>
> --
> You received this message because you are subscribed to the Google Groups "Orbeon Forms" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
> To post to this group, send email to [hidden email].



--
Hank Ratzesberger
XMLWerks.com

--
You received this message because you are subscribed to the Google Groups "Orbeon Forms" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Reply | Threaded
Open this post in threaded view
|

Re: How to advice - many forms to many instances

Hank Ratzesberger-3
In reply to this post by Alessandro Vernet
Hi Alex,

A great idea, I'm rather surprised the Orbeon engine is this clever.
This pattern will create a group to match the kind of element that needs
editing and it will edit the main instance directly. It displays/creates the
group only when the ref is relevant (matches the name).

       <xf:repeat nodeset="lb:changeSet" id="change-sets">
            <xf:var name="this" value="*"/>
            <xf:var name="nameOf" value="name(*)"/>

            <xf:group ref=".[$nameOf = 'loadData']">
                <xf:label>Load Data</xf:label>
                <xf:input ref="$this/@catalogName">
                     <xf:label>Catalog Name:</xf:label>
                </xf:input>
           ....

           <xf:group ref=".[$nameOf = 'addColumn']">
                <xf:label>Add Column</xf:label>
                <xf:input ref="$this/@tableName">
                     <xf:label>Table Name:</xf:label>
               </xf:input>


One thing is I needed to create a variable, $this for the reference to
bind in the control. The controls did not appear for example:

<xf:input ref="@schemaName">
<xf:input ref="./@schemaName">

only this works:

<xf:input ref="$this/@schemaName">

Very best,
Hank


On Mon, Jan 12, 2015 at 6:09 PM, Alessandro  Vernet <[hidden email]> wrote:

> Hi Hank,
>
> If I understand the problem, the typical way of doing this is as follows:
>
> <xf:repeat nodeset="changeSet">
>       <xf:var name="thing" value="*"/>
>       <xf:var name="nameOf" value="name(*)"/>
>       <xf:group ref=".[$nameOf = 'createTable']">
>           UI elements to edit a "createTable"
>       </xf:group>
>       <xf:group ref=".[$nameOf = 'addColumn']">
>           UI elements to edit a "addColumn"
>       </xf:group>
>       …
> </xf:repeat>
>
> In fact, initially, this is what Form Builder (which is itself using XForms)
> was doing, with an xf:repeat iterating over the controls in the source of
> the form you were editing, and then "selecting" which control to show based
> on the actual control in the XForms source.
>

--
Hank Ratzesberger
XMLWerks.com

--
You received this message because you are subscribed to the Google Groups "Orbeon Forms" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].