[Xsltforms-support] Experimental Component control (Was: A couple of questions about subforms)
Brought to you by:
alain-couthures
From: Alain C. <ala...@ag...> - 2013-06-01 21:03:21
|
Hi Eric, I have implemented a new component control in XSLTForms. It is named "xf:component" and has two attributes named "@ref" and "@resource". There are still restrictions within a component: ids cannot be used if the component is to be instantiated more than once. The default instance is local to each instantiated component and the subform-instance() function can be used to get the document element of it. From the main form to the component, a binding with a special mip named "changed" is defined. The subform-context() allows to reference the node bound to the component control in the main form. The corresponding build has been committed to repositories: http://sourceforge.net/p/xsltforms/code/ci/master/tree/build/ Performance can surely be optimized (component source is currently loaded as many time as instantiated...) and this new control has been tested only in this limited test case: figures.xml: <?xml-stylesheet href="xsltforms/xsltforms.xsl" type="text/xsl"?> <xh:html xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events"> <xh:head> <xh:title>Figures</xh:title> <xf:model> <xf:instance id="main"> <figures> <rectangle height="10in" width="4em"/> <circle radius="8%"/> </figures> </xf:instance> </xf:model> </xh:head> <xh:body> <xf:repeat ref="*"> <xf:output value="name()"/> <ul> <xf:repeat ref="@*"> <li> <xf:component ref="." resource="size.xml"/> <xf:output value="concat(' = ',.)"/> </li> </xf:repeat> </ul> </xf:repeat> </xh:body> </xh:html> size.xml: <?xml-stylesheet href="xsltforms/xsltforms.xsl" type="text/xsl"?> <xh:html xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ev="http://www.w3.org/2001/xml-events"> <xh:head> <xh:title>Size</xh:title> <xf:model> <xf:instance> <size> <value xsi:type="xsd:decimal">2</value> <unit>cm</unit> </size> </xf:instance> <xf:bind ref="subform-instance()/value" changed="translate(subform-context(), '%incmptxe', '')"/> <xf:bind ref="subform-instance()/unit" changed="translate(subform-context(), '0123456789', '')"/> </xf:model> </xh:head> <xh:body> <xf:input ref="subform-instance()/value" incremental="true"> <xf:label><xf:output value="local-name(subform-context())"/>: </xf:label> <xf:setvalue ev:event="xforms-value-changed" ref="subform-context()" value="concat(subform-instance()/value, subform-instance()/unit)"/> </xf:input> <xf:select1 ref="subform-instance()/unit"> <xf:label/> <xf:item> <xf:label>pixels</xf:label> <xf:value>px</xf:value> </xf:item> <xf:item> <xf:label>font size</xf:label> <xf:value>em</xf:value> </xf:item> <xf:item> <xf:label>font height</xf:label> <xf:value>ex</xf:value> </xf:item> <xf:item> <xf:label>inches</xf:label> <xf:value>in</xf:value> </xf:item> <xf:item> <xf:label>centimeters</xf:label> <xf:value>cm</xf:value> </xf:item> <xf:item> <xf:label>millimeters</xf:label> <xf:value>mm</xf:value> </xf:item> <xf:item> <xf:label>points</xf:label> <xf:value>pt</xf:value> </xf:item> <xf:item> <xf:label>picas</xf:label> <xf:value>pc</xf:value> </xf:item> <xf:item> <xf:label>%</xf:label> <xf:value>%</xf:value> </xf:item> <xf:setvalue ev:event="xforms-value-changed" ref="subform-context()" value="concat(subform-instance()/value, subform-instance()/unit)"/> </xf:select1> </xh:body> </xh:html> Thank you for your feedbacks! -Alain > 2) My subform has a local instance and I need to move data between the > current node in the main form and the subform local instance. The > context node appears to be available in the XForms controls (I can write > <xf:output ref="."/> and the current node in the main form is displayed) > but I don't know how to access this node in actions in the subform. Is > there a function I can use for that? > > For this use case we need: > > * A way to access the context node to which the "component" is > bound in the caller form. An extension function would be fine > for that. > * A way to define and access a local instance "private" to the > component. In this specific case the component needs only one > instance but I am sure we can find more complex cases where > several instances would be more convenient in which case > anonymous instances wouldn't work. > * We also need to receive events such as xforms-ready in the > component. > > In don't know if you're familiar with Orbeon's XBL implementation [1] > but this component would be defined as: > > [1] > http://wiki.orbeon.com/forms/doc/developer-guide/xbl-components-guide > > <xbl:xbl script-type="application/xhtml+xml"> > <xbl:binding id="my-dimension" element="my|dimension" xxbl:mode="lhha > binding value"> > <xbl:handlers> > <xbl:handler event="xforms-enabled xforms-value-changed"> > <xf:setvalue ref="instance('my-dimension-instance')/value" > value="translate(xxf:binding('my-dimension'), '%incmptxe', '')"/> > <xf:setvalue ref="instance('my-dimension-instance')/unit" > value="translate(xxf:binding('my-dimension'), '0123456789', '')"/> > </xbl:handler> > </xbl:handlers> > <xbl:implementation> > <xf:model id="my-dimension-model"> > <xf:instance id="my-dimension-instance"> > <dimension> > <value/> > <unit/> > </dimension> > </xf:instance> > <xf:setvalue ev:event="xforms-value-changed" > ev:observer="my-dimension-value-control" > ref="xxf:binding('my-dimension')" > value="concat(instance('my-dimension-instance')/value, > instance('my-dimension-instance')/unit)"/> > <xf:setvalue ev:event="xforms-value-changed" > ev:observer="my-dimension-unit-control" > ref="xxf:binding('my-dimension')" > value="concat(instance('my-dimension-instance')/value, > instance('my-dimension-instance')/unit)"/> > </xf:model> > </xbl:implementation> > <xbl:template> > <xf:input ref="value" id="my-dimension-value-control"/> > <xf:select1 ref="unit" id="my-dimension-unit-control"> > <xf:label/> > <xf:item> > <xf:label>pixels</xf:label> > <xf:value>px</xf:value> > </xf:item> > .../... > </xf:select1> > </xbl:template> > </xbl:binding> > </xbl:xbl> > > I won't go into the details, but see how: > > * The bound node in the caller form instance is accessed through > "xxf:binding('my-dimension')" (where "my-dimension" is the > component's id) > * Local (private) instances can have ids and are accessed through > the standard instance() function > ("instance('my-dimension-instance')" in our case) > * A handler section is used to define event handlers for events > coming "from the external". > > |