XForms/Relevant
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 > 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>
有時您會有一系列很多專案,一個專案的顯示取決於其他專案的值。謂詞是將 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][. > 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()" 無法按預期工作。必須使用字串比較。
此示例顯示如何根據 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>。
以下行是執行實際繫結的行。在將一個例項繫結到另一個例項時,您應該使用 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 示例。