跳转到内容

XForms/Relevant

来自维基教科书,开放世界中的开放书籍

使用 Relevant 属性与 Bind

[编辑 | 编辑源代码]

XForms 还允许您根据实例数据中的某个值有条件地显示表单的一部分。通常,这用于当表单的一个字段的答案有条件地显示表单的另一部分时。

该格式是在 xf:model 中使用 xf:bind 语句。

<xf:model>
   <xf:bind nodeset="NodeYowWantToConditionallyDisplay" relevant="XPathExpression"/>
</xf:model>

以下示例演示了这一点。

[编辑 | 编辑源代码]

Relevancy 演示 注意:示例应用程序中的 RelevancySelector.xhtml 不完整。

绑定到十进制数

[编辑 | 编辑源代码]

在以下示例中,第二个输入字段根据第一个实例值的整数值有条件地显示。

<html
   xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xf="http://www.w3.org/2002/xforms"
   xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <title>Testing the XForms bind relevant attribute.</title>
   <head>
   <xf:model>
      <xf:instance>
         <var xmlns="">
            <first>1</first>
            <second>This is the second value</second>
         </var>
      </xf:instance>
      <xf:bind nodeset="/var/first" type="xs:decimal" />
      <xf:bind nodeset="/var/second" relevant="/var/first &gt; 0" />
   </xf:model>
   </head>
   <body>
      <p>Demonstration of relevant fields.</p>
      <xf:select1 ref="/var/first" >
         <xf:label>Should I show the second question? </xf:label>
         <br />
         <xf:item select="yes">
            <xf:label>Yes Please!</xf:label>
            <xf:value>1</xf:value>
         </xf:item>
         <xf:item>
            <xf:label>No Thank You</xf:label>
            <xf:value>0</xf:value>
         </xf:item>
      </xf:select1>
      <br />
      <xf:input ref="/var/second">
         <xf:label>Second value: </xf:label>
      </xf:input>
   </body>
</html>

在 Bind 中使用多个谓词

[编辑 | 编辑源代码]

有时您会有一系列很多项目,一个项目的显示取决于其他项目的值。谓词是将 AND/OR 操作附加到用作相关性表达式的路径表达式末尾的一种方法。

以下示例使用带两个谓词的 bind。序列中的第二个项目绑定到第一个项目。要做到这一点,您必须在节点集中选择第二个项目 item[2],并在 item[1] 谓词的末尾添加 [. > 2.0]

<html
   xmlns="http://www.w3.org/1999/xhtml" 
   xmlns:xf="http://www.w3.org/2002/xforms"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <head>
      <xf:model>
         <xf:instance id="instanceData">
            <data xmlns="">
               <item>0.00</item>
               <item>0.00</item>
            </data>
         </xf:instance>
         <!-- this rule will only allow the second item to be displayed if the first value is over 2.0 -->
         <xf:bind nodeset="instance('instanceData')/item[2]" relevant="instance('instanceData')/item[1][. &gt; 2.0]" />
      </xf:model>
   </head>
   <body>
      <xf:input ref="instance('instanceData')/item[1]">
         <xf:label>First item: </xf:label>
      </xf:input>
      <br />
      <xf:input ref="instance('instanceData')/item[2]">
         <xf:label>Second item: </xf:label>
      </xf:input>
   </body>
</html>

绑定到布尔值

[编辑 | 编辑源代码]

由于表单的一部分通常是可见的,或者不可见的,所以使用布尔值来确定是否应该显示该字段是很自然的。

在此示例中,如果 InputIndicator 为 true,则第二个输出实例可见。

如果 InputIndicator 为 false,则第二个输出不可见。

请注意,使用了表达式 .='true'。这是一个字符串比较。理想情况下,您只需能够使用 mynoode=true() 测试节点,但我使用这种方法遇到了问题。

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" 
  xmlns:xf="http://www.w3.org/2002/xforms" 
  xmlns:ev="http://www.w3.org/2001/xml-events" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <head>
      <title>Example of binding to to boolean controls</title>
   </head>
   <body>
      <xf:model id="model">
         <xf:instance id="input">
            <DataIn xmlns="">
               <InputIndicator>false</InputIndicator>
            </DataIn>
         </xf:instance>
         <!-- make the input data type be a XML Schema type boolean -->
         <xf:bind id="input_bind" nodeset="/DataIn/InputIndicator" type="xs:boolean"></xf:bind>
         <!-- second instance bound to outputs -->
         <xf:instance id="output">
            <DataOut xmlns="">
               <OutputValue>Hello World!</OutputValue>
            </DataOut>
         </xf:instance>
         <!-- if the input is true, then the output is relevent -->
         <xf:bind id="output_bind" nodeset="instance('output')/OutputValue" relevant="instance('input')/InputIndicator[.='true']"/>
      </xf:model>
      <p>
         <xf:input bind="input_bind">
            <xf:label>Check to see the value of output: </xf:label>
         </xf:input>
     <br/>
         <xf:output bind="output_bind">
            <xf:label>Value of Output: </xf:label>
         </xf:output>
      </p>
   </body>
</html>

在此示例中,使用了一个简单的复选框来有条件地显示一个字段。

<html
   xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xf="http://www.w3.org/2002/xforms"
   xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <title>Testing the relevant attribute of the bind element with boolean values.</title>
   <xf:model>
      <xf:instance>
         <var xmlns="">
            <first>true</first>
            <second/>
         </var>
      </xf:instance>
      <xf:bind nodeset="/var/first" type="xs:boolean" />
      <xf:bind nodeset="/var/second" relevant="/var/first='true'" />
   </xf:model>
   <body>
      <p>The input field should only display if the first value is checked.</p>
      <xf:input ref="/var/first">
         <xf:label>Display the next input?: </xf:label>
      </xf:input>
      <br />
      <xf:input ref="/var/second">
         <xf:label>Display this only if the first answer is true: </xf:label>
      </xf:input>
   </body>
</html>

在此示例中,对布尔值的类型转换没有任何影响,因为 relevant="/var/first=true()" 无法按预期工作。必须使用字符串比较。

将视图绑定到 select 1

[编辑 | 编辑源代码]

此示例显示如何根据 select1 控件的值有条件地显示视图。

<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xf="http://www.w3.org/2002/xforms"
   xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <title>Testing the XForms bind relevant attribute based on a select1 control.</title>
   <xf:model>
      <xf:instance>
         <data xmlns="">
            <select1value>1</select1value>
            <view1 />
            <view2 />
            <view3 />
         </data>
      </xf:instance>
      <xf:bind nodeset="/data/select1value" type="xs:decimal" />
      <xf:bind nodeset="/data/view1" relevant="/data/select1value = 1" />
      <xf:bind nodeset="/data/view2" relevant="/data/select1value = 2" />
      <xf:bind nodeset="/data/view3" relevant="/data/select1value = 3" />
   </xf:model>
   <body>
      <p>Demonstration of relevant fields.</p>
      <xf:select1 ref="/data/select1value">
         <xf:label>What view would you like to see? </xf:label>
         <br />
         <xf:item select="yes">
            <xf:label>View 1</xf:label>
            <xf:value>1</xf:value>
         </xf:item>
         <xf:item>
            <xf:label>View 2</xf:label>
            <xf:value>2</xf:value>
         </xf:item>
          <xf:item>
            <xf:label>View 3</xf:label>
            <xf:value>3</xf:value>
         </xf:item>
      </xf:select1>
      <br />
      <xf:input ref="/data/view1">
         <xf:label>First view: </xf:label>
      </xf:input>
      <xf:input ref="/data/view2">
         <xf:label>Second view: </xf:label>
      </xf:input>
      <xf:input ref="/data/view3">
         <xf:label>Third view: </xf:label>
      </xf:input>
   </body>
</html>

请注意,功能类似于 <xf:switch> 和 <xf:case> 组合,但未使用 <xf:toggle>。

bind 语句

[编辑 | 编辑源代码]

以下行是执行实际绑定的行。在将一个实例绑定到另一个实例时,您应该使用 instance() 函数。

还要注意,您必须将 InputIndicator(句点)的文本与 true 进行比较,而不是将 InputIndicator 本身进行比较。

<xf:bind id="output_bind"
   nodeset="instance('output')/OutputValue"
   relevant="instance('input')/InputIndicator[.='true']" />

条件视图和用户可维护规则的架构

[编辑 | 编辑源代码]

有时您需要一种一致的方法来有条件地显示表单中的视图。例如,如果您希望非程序员维护视图显示时的业务逻辑,则可以由外部规则引擎生成绑定到视图的规则。

要使此方法起作用,您需要创建一个用于控制表单视图的中央实例。

<xf:instance id="views" xmlns="">
   <data>
      <named-view-1/>
      <named-view-2/>
      <named-view-3/>
   </data>
</xf:instance>

我们将此架构称为“命名视图”架构,因为可以利用外部工具来声明任何命名视图的渲染规则。这将是表单中的一个中心位置,它生成视图实例和绑定表达式。

每个视图都包装在一个组元素中,该元素将组绑定到视图中的实例。

<xf:group ref="instance('views')/named-view-1">
   <!-- these elements will be conditionally displayed based on the relevancy of named-view-1 -->
</xf:group>

<xf:group ref="instance('views')/named-view-2">
   <!-- these elements will be conditionally displayed based on the relevancy of named-view-2 -->
</xf:group>

<xf:group ref="instance('views')/named-view-2">
   <!-- these elements will be conditionally displayed based on the relevancy of named-view-3 -->
</xf:group>

然后,每个视图的显示规则可以存储在 bind 语句中。

<xf:bind nodeset="instance('views')/named-view-1" relevant="XPath-expression-that-returns-a-boolean-for named-view-1"/>
<xf:bind nodeset="instance('views')/named-view-2" relevant="XPath-expression-that-returns-a-boolean-for named-view-2"/>
<xf:bind nodeset="instance('views')/named-view-3" relevant="XPath-expression-that-returns-a-boolean-for named-view-3"/>

然后,每个表单都可以有一个“规则文件”,它看起来类似于以下内容。

<form-rules-file>
   <form-id>my-form-ver-2</form-id>
   <display-rule>
      <named-view>named-view-1</named-view>
      <xpath-expression>XPath-expression-that-returns-a-boolean-for named-view-1</xpath-expression>
   </display-rule>
   <display-rule>
      <named-view>named-view-2</named-view>
      <xpath-expression>XPath-expression-that-returns-a-boolean-for named-view-2</xpath-expression>
   </display-rule>
   <display-rule>
      <named-view>named-view-2</named-view>
      <xpath-expression>XPath-expression-that-returns-a-boolean-for named-view-3</xpath-expression>
   </display-rule>
</form-rules-file>

然后,您可以构建另一个 XForms 应用程序,允许非程序员维护这些规则文件,以及一个简单的转换,在加载 XForms 模型时将实例和 bind 语句置于 XForms 模型中。可能仍然需要手动将原始组添加到表单中,但添加视图后,可以使用单独的应用程序维护规则。

更改要显示的字段

[编辑 | 编辑源代码]

以下示例,如果国家代码为“usa”,则有条件地显示两个邮政编码字段,或者如果字段不是“usa”,则显示邮政编码。

<html
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xf="http://www.w3.org/2002/xforms"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <head>
        <title>Testing the XForms bind relevant attribute.</title>
        <style language="text/css">
            <![CDATA[
    @namespace xf url("http://www.w3.org/2002/xforms");

     /* this allows the descenders (jpqy) to be visible in the drop down list */
     xf|select1 .xf-value {height: 1.5em;} 
     
     .ZipCode .xf-value {width:5ex}
     .ZipCodeSuffix .xf-value {width:4ex}
     .PostalCode .xf-value {width:10ex}
    ]]>
        </style>
        <xf:model>
            <xf:instance xmlns="" id="save-data">
                <data>
                    <CountryCode>usa</CountryCode>
                    <ZipCode>12345</ZipCode>
                    <ZipCodeSuffix>1234</ZipCodeSuffix>
                    <PostalCode>AB-1234</PostalCode>
                </data>
            </xf:instance>
            
            <!-- The views instance are boolean values that tell what fields are visible -->
            <xf:instance xmlns="" id="views">
                <data>
                    <DisplayZipCode/>
                    <DisplayPostalCode/>
                </data>
            </xf:instance>
            
            <!-- this rule only displays the zip code if the country code is 'usa'-->
            <xf:bind id="DisplayZipCode"
                nodeset="instance('views')/DisplayZipCode" 
                relevant="instance('save-data')/CountryCode='usa'" />
            <xf:bind id="DisplayPostalCode"
                nodeset="instance('views')/DisplayPostalCode" 
                relevant="not(instance('save-data')/CountryCode='usa')" />
            
        </xf:model>
    </head>
    <body>
        <p>Demonstration of binding Zip Code Input</p>
        
        <xf:select1 ref="instance('save-data')/CountryCode" selection="open">
            <xf:label>Country:</xf:label>
            <xf:item>
                <xf:label>USA</xf:label>
                <xf:value>usa</xf:value>
            </xf:item>
            <xf:item>
                <xf:label>Canada</xf:label>
                <xf:value>can</xf:value>
            </xf:item>
            <xf:item>
                <xf:label>Mexico</xf:label>
                <xf:value>mex</xf:value>
            </xf:item>
            <xf:item>
                <xf:label>Other</xf:label>
                <xf:value>other</xf:value>
            </xf:item>
        </xf:select1>
        <br/>
        
        <xf:group bind="DisplayZipCode">
            <xf:input ref="instance('save-data')/ZipCode" class="ZipCode">
                <xf:label>Zip Code: </xf:label>
            </xf:input>
            <xf:input ref="instance('save-data')/ZipCodeSuffix" class="ZipCodeSuffix">
                <xf:label>-</xf:label>
            </xf:input>
        </xf:group>
        <xf:input ref="instance('save-data')/LocationPostalID" bind="DisplayPostalCode" class="DisplayPostalCode">
            <xf:label>Postal Code: </xf:label>
        </xf:input>
    </body>
</html>

条件显示最常见的发生之一是重复元素的删除功能。通常,您不希望删除最后一个。请参阅 XForms/Conditional delete 示例。

下一页: 显示-隐藏控件 | 上一页: Switch and Case
首页: XForms
华夏公益教科书