How can I set the relevant property of an Orbeon e

2020-05-07 11:22发布

问题:

I am trying to create in a form some elements that are visible if one specific element has been visited or not. Is it possible?

At this moment, I only can achieve this copying the relevant part of the first element to the others one, but, in the case on one element depends on many others elements, the relevant rule is too large. Then I am looking for some way to simply this: is there any kind of function like "isVisible()"?

Something like (i.e. control-2 must be visible only if control-1 is visible):

<xf:bind id="control-2-bind" ref="control-2" name="control-2" relevant="isVisible($control-1)"/>

EDITED: An example of form, where control-5 must be shown only if control-4 is shown.

<xh:html xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms"
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:ev="http://www.w3.org/2001/xml-events"
     xmlns:xi="http://www.w3.org/2001/XInclude"
     xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
     xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
     xmlns:exf="http://www.exforms.org/exf/1-0"
     xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
     xmlns:saxon="http://saxon.sf.net/"
     xmlns:sql="http://orbeon.org/oxf/xml/sql"
     xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
     xmlns:xxforms="http://orbeon.org/oxf/xml/xforms"
     xmlns:fb="http://orbeon.org/oxf/xml/form-builder">
<xh:head>
    <xh:title>Untitled Form</xh:title>
    <xf:model id="fr-form-model" xxf:expose-xpath-types="true">

        <!-- Main instance -->
        <xf:instance id="fr-form-instance">
            <form>
                <section-1>
                    <control-3/>
                    <control-4/>
                    <control-5/>

                </section-1>
            </form>
        </xf:instance>

        <!-- Bindings -->
        <xf:bind xmlns:dataModel="java:org.orbeon.oxf.fb.DataModel" id="fr-form-binds"
                 ref="instance('fr-form-instance')">
            <xf:bind id="section-1-bind" name="section-1" ref="section-1">
                <xf:bind id="control-3-bind" ref="control-3" name="control-3"/>
                <xf:bind id="control-4-bind" ref="control-4" name="control-4"
                         relevant="$control-3='one'"/>
                <xf:bind id="control-5-bind" ref="control-5" name="control-5"
                         relevant="xxforms:visited($control-4)"/>

            </xf:bind>
        </xf:bind>

        <!-- Metadata -->
        <xf:instance xxf:readonly="true" id="fr-form-metadata">
            <metadata>
                <application-name>asd</application-name>
                <form-name>asd</form-name>
                <title xml:lang="en">Untitled Form</title>
                <description xml:lang="en"/>
            </metadata>
        </xf:instance>

        <!-- Attachments -->
        <xf:instance id="fr-form-attachments">
            <attachments>
                <css mediatype="text/css" filename="" size=""/>
                <pdf mediatype="application/pdf" filename="" size=""/>
            </attachments>
        </xf:instance>

        <!-- All form resources -->
        <!-- Don't make readonly by default in case a service modifies the resources -->
        <xf:instance id="fr-form-resources" xxf:readonly="false">
            <resources>
                <resource xml:lang="en">
                    <control-3>
                        <item>
                            <label>First choice</label>
                            <value>one</value>
                        </item>
                        <item>
                            <label>Second choice</label>
                            <value>two</value>
                        </item>
                        <item>
                            <label>Third choice</label>
                            <value>three</value>
                        </item>
                        <label/>
                        <hint/>
                    </control-3>
                    <control-4>
                        <label>Input</label>
                        <hint/>
                    </control-4>
                    <control-5>
                        <label>Visited</label>
                        <hint/>
                    </control-5>
                    <section-1>
                        <label>Untitled Section</label>
                    </section-1>

                </resource>
            </resources>
        </xf:instance>

        <!-- Utility instances for services -->
        <xf:instance id="fr-service-request-instance" xxf:exclude-result-prefixes="#all">
            <request/>
        </xf:instance>

        <xf:instance id="fr-service-response-instance" xxf:exclude-result-prefixes="#all">
            <response/>
        </xf:instance>

    </xf:model>
</xh:head>
<xh:body>
    <fr:view>
        <fr:body xmlns:xbl="http://www.w3.org/ns/xbl"
                 xmlns:dataModel="java:org.orbeon.oxf.fb.DataModel"
                 xmlns:oxf="http://www.orbeon.com/oxf/processors"
                 xmlns:p="http://www.orbeon.com/oxf/pipeline">
            <fr:section id="section-1-control" bind="section-1-bind">
                <xf:label ref="$form-resources/section-1/label"/>
                <fr:grid>
                    <xh:tr>
                        <xh:td>
                            <xf:select1 id="control-3-control" appearance="full" bind="control-3-bind">
                                <xf:label ref="$form-resources/control-3/label"/>
                                <xf:hint ref="$form-resources/control-3/hint"/>

                                <xf:alert ref="$fr-resources/detail/labels/alert"/>
                                <xf:itemset ref="$form-resources/control-3/item">
                                    <xf:label ref="label"/>
                                    <xf:value ref="value"/>
                                </xf:itemset>
                            </xf:select1>

                        </xh:td>

                    </xh:tr>
                    <xh:tr>
                        <xh:td>
                            <xf:input id="control-4-control" bind="control-4-bind">
                                <xf:label ref="$form-resources/control-4/label"/>
                                <xf:hint ref="$form-resources/control-4/hint"/>
                                <xf:alert ref="$fr-resources/detail/labels/alert"/>


                            </xf:input>
                        </xh:td>
                    </xh:tr>
                    <xh:tr>
                        <xh:td>
                            <xf:output id="control-5-control" bind="control-5-bind">
                                <xf:label ref="$form-resources/control-5/label"/>
                                <xf:hint ref="$form-resources/control-5/hint"/>

                                <xf:alert ref="$fr-resources/detail/labels/alert"/>
                            </xf:output>
                        </xh:td>
                    </xh:tr>
                </fr:grid>
            </fr:section>
        </fr:body>
    </fr:view>
</xh:body>

The code is not working. The control-5 is never shown. What is wrong there?

EDITED: An example using the proposed solution "instance('visited')"

<xh:html xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms"
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:ev="http://www.w3.org/2001/xml-events"
     xmlns:xi="http://www.w3.org/2001/XInclude"
     xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
     xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
     xmlns:exf="http://www.exforms.org/exf/1-0"
     xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
     xmlns:saxon="http://saxon.sf.net/"
     xmlns:sql="http://orbeon.org/oxf/xml/sql"
     xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
     xmlns:xxforms="http://orbeon.org/oxf/xml/xforms"
     xmlns:fb="http://orbeon.org/oxf/xml/form-builder">
<xh:head>
    <xh:title>Untitled Form</xh:title>
    <xf:model id="fr-form-model" xxf:expose-xpath-types="true">

    <!-- Main instance -->
    <xf:instance id="fr-form-instance">
            <form>
                <section-1>
                    <control-3/>
                    <control-4/>
                    <control-5/>
                </section-1>
            </form>
        </xf:instance>

        <!-- Bindings -->
    <xf:bind xmlns:dataModel="java:org.orbeon.oxf.fb.DataModel" id="fr-form-binds"
                 ref="instance('fr-form-instance')">
            <xf:bind id="section-1-bind" name="section-1" ref="section-1">
                <xf:bind id="control-3-bind" ref="control-3" name="control-3"/>
                <xf:bind id="control-4-bind" ref="control-4" name="control-4"
                         relevant="$control-3='one'"/>
                <xf:bind id="control-5-bind" ref="control-5" name="control-5"
                         relevant="instance('visited') = 'true' and string-length($control-4)&gt;0"/>
            </xf:bind>
        </xf:bind>

        <!-- Keep track of visited status -->
    <xf:instance id="visited">
            <visited/>
        </xf:instance>
        <xf:setvalue ev:event="xxforms-visited" observer="control-4-control"
                     ref="instance('visited')"
                     value="'true'"/>
        <xf:setvalue ev:event="xxforms-unvisited" observer="control-4-control"
                     ref="instance('visited')"
                     value="'false'"/>

        <!-- Metadata -->
    <xf:instance xxf:readonly="true" id="fr-form-metadata">
            <metadata>
                <application-name>asd</application-name>
                <form-name>asd</form-name>
                <title xml:lang="en">Untitled Form</title>
                <description xml:lang="en"/>
            </metadata>
        </xf:instance>

        <!-- Attachments -->
    <xf:instance id="fr-form-attachments">
            <attachments>
                <css mediatype="text/css" filename="" size=""/>
                <pdf mediatype="application/pdf" filename="" size=""/>
            </attachments>
        </xf:instance>

        <!-- All form resources -->
    <!-- Don't make readonly by default in case a service modifies the resources -->
    <xf:instance id="fr-form-resources" xxf:readonly="false">
            <resources>
                <resource xml:lang="en">
                    <control-3>
                        <item>
                            <label>First choice</label>
                            <value>one</value>
                        </item>
                        <item>
                            <label>Second choice</label>
                            <value>two</value>
                        </item>
                        <item>
                            <label>Third choice</label>
                            <value>three</value>
                        </item>
                        <label/>
                        <hint/>
                    </control-3>
                    <control-4>
                        <label>Input</label>
                        <hint/>
                    </control-4>
                    <control-5>
                        <label>Visited</label>
                        <hint/>
                    </control-5>
                    <section-1>
                        <label>Untitled Section</label>
                    </section-1>

                </resource>
            </resources>
        </xf:instance>

        <!-- Utility instances for services -->
    <xf:instance id="fr-service-request-instance" xxf:exclude-result-prefixes="#all">
            <request/>
        </xf:instance>

        <xf:instance id="fr-service-response-instance" xxf:exclude-result-prefixes="#all">
            <response/>
        </xf:instance>
    </xf:model>
</xh:head>
<xh:body>
    <fr:view>
        <fr:body xmlns:xbl="http://www.w3.org/ns/xbl"
                 xmlns:oxf="http://www.orbeon.com/oxf/processors"
                 xmlns:p="http://www.orbeon.com/oxf/pipeline"
                 xmlns:dataModel="java:org.orbeon.oxf.fb.DataModel">
            <fr:section id="section-1-control" bind="section-1-bind">
                <xf:label ref="$form-resources/section-1/label"/>
                <fr:grid>
                    <xh:tr>
                        <xh:td>
                            <xf:select1 id="control-3-control" appearance="full" bind="control-3-bind">
                                <xf:label ref="$form-resources/control-3/label"/>
                                <xf:hint ref="$form-resources/control-3/hint"/>

                                <xf:alert ref="$fr-resources/detail/labels/alert"/>
                                <xf:itemset ref="$form-resources/control-3/item">
                                    <xf:label ref="label"/>
                                    <xf:value ref="value"/>
                                </xf:itemset>
                            </xf:select1>

                        </xh:td>

                    </xh:tr>
                    <xh:tr>
                        <xh:td>
                            <xf:input id="control-4-control" bind="control-4-bind">
                                <xf:label ref="$form-resources/control-4/label"/>
                                <xf:hint ref="$form-resources/control-4/hint"/>
                                <xf:alert ref="$fr-resources/detail/labels/alert"/>
                            </xf:input>
                        </xh:td>
                    </xh:tr>
                    <xh:tr>
                        <xh:td>
                            <xf:output id="control-5-control" bind="control-5-bind">
                                <xf:label ref="$form-resources/control-5/label"/>
                                <xf:hint ref="$form-resources/control-5/hint"/>
                                <xf:alert ref="$fr-resources/detail/labels/alert"/>                                
                            </xf:output>
                        </xh:td>
                    </xh:tr>
                </fr:grid>
            </fr:section>
        </fr:body>
    </fr:view>
</xh:body>

In this example, if you select 'First Choice' then, the Input Field is shown. And if you fill it with any value, 'Visited' label is therefore shown. This is the expected behaviour. But, if you later change the Radio Button to 'Second Choice', the Input Field is hidden but the 'Visited' label is still visible (only will be hidden if the user deletes the value of the input field, but now is hidden). This is undesired. There is any way to avoid this?

NOTE: I have added string-length() to be sure that is hidden if the value has been removed. Without it, always is visible.

回答1:

Since Orbeon Forms 4 there is:

  • the xxf:visited() function
  • the xxforms-visited and xxforms-unvisited events

You have to be careful with dependencies when using the function, especially on xf:bind.

I tried to build a naive example, but it turns out that it doesn't work and I entered an issue.

Here is a workaround, which requires adding a custom XForms instance:

<xf:bind id="control-5-bind" ref="control-5" name="control-5"
    relevant="instance('visited') = 'true'"/>

<xf:instance id="visited"><visited/></xf:instance>
<xf:setvalue event="xxforms-visited"   observer="control-4-control" ref="instance('visited')" value="'true'"/>
<xf:setvalue event="xxforms-unvisited" observer="control-4-control" ref="instance('visited')" value="'false'"/>

And here is the complete example.



标签: orbeon xforms