xxf:valid() function - how does it work?

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

xxf:valid() function - how does it work?

bwallis42
I'm trying to disable a trigger link when a form is invalid or partially invalid. The xxforms:valid() function seems to be the right thing to use but I cannot get it to work. I need this working in an Orbeon 3.9 installation but I've tried the same thing in 2017.1 and that also doesn't work. The form is attached below.

What I have is a bind as follows, it has a readonly function that is supposed to be dependent on the validity or otherwise of a previous field (called 'field'). If the field is invalid (it is set to required) then the button shouldn't work but it does regardless of the validity of 'field'.

            <xforms:bind id="fr-form-binds" ref="instance('fr-form-instance')">
                <xforms:bind id="section-1-bind" name="section-1" ref="section-1">
                    <xforms:bind id="field-bind" name="field" ref="field" required="true()" type="xs:string"/>
                    <xforms:bind id="button-bind" name="button" ref="button" type="xforms:string"
                                 readonly="not(xxforms:valid(field))"/>
                    <xforms:bind id="time-bind" ref="time" name="time"/>
                </xforms:bind>
            </xforms:bind>

I've tried variations on this but I cannot get it to work. Is this the right way to do this? If not, what can I use to disable the trigger if some part of the form is invalid.

the full form source is

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

            <!-- Main instance -->
            <xforms:instance id="fr-form-instance" xxf:index="id">
                <form>
                    <section-1>
                        <field/>
                        <button/>
                        <time/>
                    </section-1>
                </form>
            </xforms:instance>

            <!-- Bindings -->
            <xforms:bind id="fr-form-binds" ref="instance('fr-form-instance')">
                <xforms:bind id="section-1-bind" name="section-1" ref="section-1">
                    <xforms:bind id="field-bind" name="field" ref="field" required="true()" type="xs:string"/>
                    <xforms:bind id="button-bind" name="button" ref="button" type="xforms:string"
                                 readonly="not(xxforms:valid(field,true()))"/>
                    <xforms:bind id="time-bind" ref="time" name="time"/>
                </xforms:bind>
            </xforms:bind>
            <!-- Metadata -->
            <xforms:instance xxf:readonly="true" id="fr-form-metadata"
                             xxforms:exclude-result-prefixes="#all">
                <metadata>
                    <application-name>CPF</application-name>
                    <form-name>bwtest</form-name>
                    <title xml:lang="en">Untitled Form</title>
                    <description xml:lang="en"/>
                    <version-comment/>
                </metadata>
            </xforms:instance>


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

            <!-- All form resources -->
            <!-- Don't make readonly by default in case a service modifies the resources -->
            <xforms:instance id="fr-form-resources" xxforms:readonly="false">
                <resources>
                    <resource xml:lang="en">
                        <section-1>
                            <label>Untitled Section</label>
                            <help/>
                        </section-1>
                        <field>
                            <label>field</label>
                            <hint/>
                            <help/>
                            <alert/>
                        </field>
                        <button>
                            <label>button</label>
                            <hint/>
                            <help/>
                            <alert/>
                        </button>
                        <time>
                            <label>current time</label>
                            <hint/>
                            <help/>
                            <alert/>
                        </time>
                    </resource>
                </resources>
            </xforms:instance>

            </xforms:model>
    </xhtml:head>
    <xhtml:body>
        <fr:view>
            <xforms:label ref="instance('fr-form-metadata')/title"/>
            <fr:body xmlns:xbl="http://www.w3.org/ns/xbl" xmlns:xh="http://www.w3.org/1999/xhtml"
                     xmlns:fb="http://orbeon.org/oxf/xml/form-builder"
                     xmlns:p="http://www.orbeon.com/oxf/pipeline"
                     xmlns:xf="http://www.w3.org/2002/xforms"
                     xmlns:oxf="http://www.orbeon.com/oxf/processors"
                     xmlns:xxf="http://orbeon.org/oxf/xml/xforms">
                <fr:section bind="section-1-bind" id="section-1-section">
                    <xforms:label ref="$form-resources/section-1/label"/>
                    
                    <fr:grid columns="2">
                        <xhtml:tr>
                            <xhtml:td>
                                <xforms:input bind="field-bind" id="field-control">
                                    <xforms:label ref="$form-resources/field/label"/>
                                    <xforms:hint ref="$form-resources/field/hint"/>
                                    
                                    <xforms:alert ref="$fr-resources/detail/labels/alert"/>
                                </xforms:input>
                            </xhtml:td>
                            <xhtml:td>
                                <xforms:trigger xmlns:pipeline="java:org.orbeon.oxf.processor.pipeline.PipelineFunctionLibrary"
                                                appearance="minimal"
                                                id="button-control"
                                                bind="button-bind">
                                    <xforms:label ref="$form-resources/button/label"/>
                                    
                                    <xforms:hint ref="$form-resources/button/hint"/>
                                    <xforms:alert ref="$fr-resources/detail/labels/alert"/>
                                    <xforms:action event="DOMActivate">
                                        <xforms:setvalue ref="instance('fr-form-instance')/section-1/time" value="current-time()"/>
                                    </xforms:action>
                                </xforms:trigger>
                            </xhtml:td>
                        </xhtml:tr>
                        <xhtml:tr>
                            <xhtml:td/>
                            <xhtml:td>
                                <xforms:output xmlns:pipeline="java:org.orbeon.oxf.processor.pipeline.PipelineFunctionLibrary"
                                               bind="time-bind"
                                               id="time-control">
                                    <xforms:label ref="$form-resources/time/label"/>
                                    <xforms:hint ref="$form-resources/time/hint"/>
                                    
                                    <xforms:alert ref="$fr-resources/detail/labels/alert"/>
                                </xforms:output>
                            </xhtml:td>
                        </xhtml:tr>
                    </fr:grid>
                </fr:section>
            </fr:body>
        </fr:view>
    </xhtml:body>
</xhtml:html>
Reply | Threaded
Open this post in threaded view
|

Re: xxf:valid() function - how does it work?

Erik Bruchez
Administrator
The short answer is that you cannot use `xxf:valid()` on a bind's `readonly` attribute. That's because, when recalculating the model, `readonly` is always calculated before node validity. So the validity will be out of sync. Ideally there would be dependencies between the two, so that order is determine magically. But at this point order is hardcoded.

With 2017.1, one way would be, in the view, to use a variable. Upon value change, set the validity into instance data:

<xf:var name="valid" value="xxf:valid(my-node)">
  <xf:setvalue
    event="xforms-enabled xforms-value-changed"
    ref="instance('my-instance')/is-my-subform-valid"
   value="$valid"/>
</xf:var>

Then in your bind, use the value of `is-my-subform-valid` to control your `readonly`.

It is heavy, that's for sure, but it addresses the dependency order.

Now I am not sure if much of this would work with 3.9 though.

-Erik