Using the "origin" on xf:insert simplifies the logic for xf:repeats - no need to always have a dummy row at the end of the repeat, which should not be shown to the user by cannot ever be deleted.
I started off doing repeats the way most of the examples said to do - have a dummy row at the end, which you then use as a template for the actual repeat. Problem is that this is not an elegant solution, and results in lots of places where you end up needing to code around that dummy row. The repeat cannot (should not) show the row because it's not real data and is only there for the developer's use.
I started off doing repeats the way most of the examples said to do - have a dummy row at the end, which you then use as a template for the actual repeat. Problem is that this is not an elegant solution, and results in lots of places where you end up needing to code around that dummy row. The repeat cannot (should not) show the row because it's not real data and is only there for the developer's use.
Then when you send the instance data to the server to update, you end up having to make sure that you don't try to save the dummy row into the database by mistake.
However there is a simpler way. The xf:insert tag has an attribute called "origin". This is an XPath expression that can be used to inform XForms of the location of the xml tags to be copied. Because it's just a normal XPath expression, we can use it to specify tags from other instances. This means we can separate the tags to be copied from the "real" data tags.
Using an instance for templates, separate from the instance that contains the actual data:
<xf:instance id="data">
<data xmlns="">
<clients>
<client>
<surname>Smith</surname>
<forename>John</forename>
</client>
<client>
<surname>Smith</surname>
<forename>Jill</forename>
</client>
</clients>
</data>
</xf:instance>
<xf:instance id="data-templates">
<data xmlns="">
<client>
<surname />
<forename />
</client>
</data>
< /xf:instance>
When used in an xf:repeat sequence, it's then simple to use the "data" instance, showing all client entities.
<xf:repeat id="client-list" nodeset="instance('data')/clients/client">
Then on the xf:trigger to insert a new Client, we can use the xf:insert as:
<xf:insert
nodeset="instance('data')/clients/client"
at="1"
position="before"
origin="instance('data-templates')/client" />
Of course in order to make this work sensibly we then need to ensure that the template and the real data entities always follow the same structure. This is where the XML Schema comes in, and that's a subject for later.
However there is a simpler way. The xf:insert tag has an attribute called "origin". This is an XPath expression that can be used to inform XForms of the location of the xml tags to be copied. Because it's just a normal XPath expression, we can use it to specify tags from other instances. This means we can separate the tags to be copied from the "real" data tags.
Using an instance for templates, separate from the instance that contains the actual data:
<xf:instance id="data">
<data xmlns="">
<clients>
<client>
<surname>Smith</surname>
<forename>John</forename>
</client>
<client>
<surname>Smith</surname>
<forename>Jill</forename>
</client>
</clients>
</data>
</xf:instance>
<xf:instance id="data-templates">
<data xmlns="">
<client>
<surname />
<forename />
</client>
</data>
< /xf:instance>
When used in an xf:repeat sequence, it's then simple to use the "data" instance, showing all client entities.
<xf:repeat id="client-list" nodeset="instance('data')/clients/client">
Then on the xf:trigger to insert a new Client, we can use the xf:insert as:
<xf:insert
nodeset="instance('data')/clients/client"
at="1"
position="before"
origin="instance('data-templates')/client" />
Of course in order to make this work sensibly we then need to ensure that the template and the real data entities always follow the same structure. This is where the XML Schema comes in, and that's a subject for later.
1 comment:
Thanks for writing this.
Post a Comment