Using a bind in a repeat for row-level configuration

We have a summary page displaying up to 18 columns of data in a repeat with a variable subset of the total rows available being displayed. A couple of the columns need to be editable for only some of the rows. Is there a way to do this in xforms within a repeat?

We tried adding both an input and an output control for the columns that need to be conditionally editable, with binds so that one or the other would show for the row. This didn't work along with many other permutations. It is quite possible we are not specifying the bind conditions properly, as we have not found any information related to using a bind in a repeat in this fashion.

If this can be done how can it be done?

Here's a highly simplified example of what didn't work. Neither the input or the output control showed for the hours column.

<xforms:model id="main-model">

<xforms:instance id="summary-data">
<olist xmlns="">
<os_full>
<actuals>
<name>a</name>
<hours>1</hours>
<editable>1</editable>
<edit></edit>
<display></display>
</actuals>
</os_full>
<os_full>
<actuals>
<name>b</name>
<hours>2</hours>
<editable>0</editable>
<edit></edit>
<display></display>
</actuals>
</os_full>
<os_full>
<actuals>
<name>c</name>
<hours>3</hours>
<editable>1</editable>
<edit></edit>
<display></display>
</actuals>
</os_full>
</olist>
</xforms:instance>

<xforms:bind id="edit_actuals" nodeset="instance('summary-data')/os_full/actuals/edit"
relevant="instance('summary-data')/os_full_actuals/editable = '1'"/>
<xforms:bind id="display_actuals" nodeset="instance('summary-data')/os_full/actuals/display"
relevant="instance('summary-data')/os_full_actuals/editable != '1'"/>

</xforms:model>

<body>

<xforms:repeat nodeset="instance('summary-data')/os_full/actuals">
<xforms:output ref="name" style="width=50px;" class=""/>
<xforms:group bind="display_actuals">
<xforms:output ref="hours" style="width=50px;" class=""/>
</xforms:group>
<xforms:group bind="edit_actuals">
<xforms:input ref="hours" style="width=50px;" class=""/>
</xforms:group>
<br>
</xforms:repeat>

</body>

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Typo, Context, and bind confusions.

There are a few things going on here, which I will deal with in order of complexity. The first, I suspect, is a typo: The relevant attributes seem to point to nodes that don't exist -
relevant="instance('summary-data')/os_full_actuals/editable = '1'" There is no element "os_full_actuals" in your instance data. I assume that what is meant here is os_full/actuals? As it stands, the "relevant" Model Item Property is being set to false for all the nodes referenced by "edit_actuals", and true for all of the nodes in "display_actuals".

The second issue regards the evaluation context of the XPath expressions. If "os_full_actuals" really is a typo, correcting it will still not yield the results I suspect you desire. Because the "relevant" XPath expression starts with instance('summary_data'), you are effectively ignoring the context given by nodeset. In this case, all nodes referenced by "edit_actuals" will have relevant set to true, because the XPath expression governing relevance always points to the first "editable" element in the instance document (which has the value, "1"). In order to get a different value for each node, you need to define an XPath expression that will respect the context in which it is evaluated. I would recommend something like relevant="../editable"

I glean from the attachment you emailed me that the third issue appears to be some confusion in the relationship between the bind element, the bind attribute, and the instance data. Here is the section that leads me to that conclusion.


      <xforms:group bind="display_actuals" ref="hours">
        <xforms:output ref="."/>
      </xforms:group>
      <xforms:group bind="edit_actuals" ref="hours">
        <xforms:input ref="."/>
      </xforms:group>

What is happening here is almost the same as in the example in your post above, except that because the input and output now have ref="." instead of ref="hours", they now bind to the first edit and display elements, instead of to nothing at all. When an xforms element has both a bind attribute and a ref or nodeset attribute, in order to resolve the instance data node, the bind attribute takes precedence (See: 3.2.3 Single-Node Binding Attributes). In this example, ref="hours", on the group element, is completely ignored.

The bind element applies model item properties and schema constraints to the instance data, so that regardless of how an instance data node is referenced, it will have the same properties. i.e. in the following example, the first three inputs will be exactly alike, as will the third, as long as instance('i')/a/b points to the first element called "b" in document order.


<xf:bind id="theBind" nodeset="instance('i')/a/b" readonly="true()" />
...
<xf:input bind="theBind" id="i0" />
<xf:input ref="instance('i')/a/b" id="i1" />
<xf:group ref="instance('i')/a">
	<xf:input ref="b" id="i2" />
</xf:group>
<xf:input ref="instance('i')//b" id="i3" />

I also find it interesting that you are using the "relevant" Model Item Property, rather than readonly to realize what seems to be a conceptual property called "editable". Using readonly will also prevent the non-editable fields from being written to.

In order to achieve the results you desire, I suggest something like the following:
Set the readonly property of the field that you actually wish to be editable or non-editable:


   <xforms:bind id="edit_actuals" nodeset="instance('summary-data')/os_full/actuals/hours"
      readonly="../editable != '1'"/>

Set up some style rules that hide the inputs and outputs based on the value of the readonly property.


      <style>
         .hide_read_write .pc-read-write,
         .hide_read_only .pc-read-only
        {
        display:none;
        }
      </style>

Define the repeat.


      <xforms:repeat nodeset="instance('summary-data')/os_full/actuals">
        <xforms:output ref="name" />
        <xforms:group  ref="hours" class="hide_read_write">
         <xforms:output ref="." />
         </xforms:group>

        <xforms:group  ref="hours" class="hide_read_only">
          <xforms:input ref="." />
         </xforms:group>
        <br>
      </xforms:repeat>

bind + Single node Binding applies first node rule.

If you have a bind attribute on an element that takes single node binding attributes, such as the group in your sample. The element is bound to the first node in the nodeset exposed by the bind. This means that in the example you give, although three iterations of the repeat will appear, the two groups in each iteration will be bound to the same node in the instance data.

Since the ref attribute present on the input and output in each is executed in the context of the immediately enclosing binding, the only difference between each iteration will be the output with ref="name".

Use the ref attribute on your groups, and the example you give will behave as desired.

Hi I´m learning all about

Hi

I´m learning all about this item and I want to know if someone can help me and give me more information or links of all this....

Thanks a lot

Bye

______________________________
Submited by : Libros Gratis

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.