跳轉到內容

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
華夏公益教科書