跳到內容

XRX/伺服器欄位驗證

來自華夏公益教科書,開放的書籍,開放的世界
< XRX

您在表單欄位中擁有要驗證的資料。例如,您要驗證郵政編碼是否有效。您希望在伺服器上執行驗證,因為將完整資料集載入到 Web 瀏覽器中進行驗證會減慢表單載入速度。

向遠端伺服器傳送資料並將結果返回,而不會重新載入整個表單,是 XForms 的核心功能。XRX 的優勢在於,可以在不編寫任何 JavaScript 程式碼的情況下實現這一功能。我們將使用幾個元件演示此技術。

  1. 我們將建立一個伺服器端 RESTful 元件,如果欄位通過了伺服器端檢查,則返回一個簡單的“OK”訊息,如果失敗,則返回一個錯誤訊息。
  2. 我們將向該欄位新增一個操作,以檢測該欄位中的值是否更改。這可以針對使用者鍵入的每個字元執行,或者當用戶從該欄位中跳出時執行。
  3. 此操作將觸發對伺服器的提交併返回結果到模型中。RESTful 服務的輸入引數和服務結果將儲存在模型中的單獨例項中。

示例程式碼

[編輯 | 編輯原始碼]

在此示例中,我們將檢查輸入的資料是否為有效的郵政編碼(美國郵政編碼)。

這是來自表單的示例程式碼

輸入欄位

[編輯 | 編輯原始碼]

在以下程式碼中,我們將 XForms 操作新增到輸入中。我們觸發的事件是 **DOMFocusOut**,它在使用者從欄位中跳出時觸發。我們執行兩個操作。

  1. 我們使用 xf:setvalue 函式將值放入傳出例項中。
  2. 我們觸發 RESTful Web 服務。

輸入欄位和操作的示例程式碼片段

[編輯 | 編輯原始碼]
<xf:input ref="zip-code" incremental="true">
    <xf:label>Zip Code:</xf:label>
    <xf:hint>Five digit zip code</xf:hint>
    <xf:action ev:event="DOMFocusOut">
        <!-- copy the value in the form to the outgoing submission instance -->
        <xf:setvalue ref="instance('zip-check')/zip-code" value="instance('save-data')/zip-code"/>
        <xf:send submission="zip-check-submission"/>
    </xf:action>
</xf:input>

提交元素

[編輯 | 編輯原始碼]

這是新增到 XForms 模型中的附加提交元素。方法為 HTTP GET,它將我們傳出“zip-check”例項中的所有引數新增到 URL 的末尾。操作是 XQuery 指令碼的名稱。在本例中,我使用了一個相對路徑,這在 XQuery 檢查與生成 XForms 應用程式的 XQuery 指令碼位於同一集合中時很常見。

<xf:submission id="zip-check-submission" method="get" action="zip-check.xq" 
       ref="instance('zip-check-submission')" 
       replace="instance" instance="zip-check-results" 
       separator=";"/>

傳出值和傳入結果的例項

[編輯 | 編輯原始碼]
 <!-- store the outgoing query parameters for the zip check. -->
    <xf:instance id="zip-check">
        <data xmlns="">
            <zip-code/>
        </data>
    </xf:instance>
    
    <!-- a place to store the results of a check -->
    <xf:instance id="zip-check-results">
        <data xmlns=""/>
    </xf:instance>

這將導致查詢的結果成為 URL 引數。

zip-check.xq?zip-code=55426

伺服器端 XQuery 示例

[編輯 | 編輯原始碼]

伺服器端 XQuery 示例

[編輯 | 編輯原始碼]
xquery version "1.0";

let $file-path := '/db/org/syntactica/wiki-books/xrx/field-server-check/zip-codes.xml'
let $zip-codes := doc($file-path)/code-table/items/item/value

let $zip-code := request:get-parameter('zip-code', '')

return
<results>{
   if (some $item in $zip-codes satisfies ($zip-code = $item))
     then
        <message class="ok">OK</message>
     else
        <message class="error">{concat('zip-code: ', $zip-code, ' is not valid.')}</message>
}</results>

正確值的示例響應

[編輯 | 編輯原始碼]
<results>
   <message class="ok">OK</message>
</results>
<results>
   <message class="error">zip-code: 55999 is not valid.</message>
</results>

示例資料檔案

[編輯 | 編輯原始碼]
<code-table>
    <name>zip-code</name>
    <items>
        <item>
            <label>St. Louis Park, MN</label>
            <value>55426</value>
        </item>
        <item>
            <label>Mendota Heights, MN</label>
            <value>55118</value>
        </item>
        <item>
            <label>Minneapolis, MN</label>
            <value>55401</value>
        </item>
        <item>
            <label>Edina, MN</label>
            <value>55439</value>
        </item>
    </items>
</code-table>

完整的 XForms 示例

[編輯 | 編輯原始碼]
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ev="http://www.w3.org/2001/xml-events"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xf="http://www.w3.org/2002/xforms">
    <head>
        <title>Form Title</title>
        <style type="text/css"><![CDATA[
            
            @namespace xf url("http://www.w3.org/2002/xforms");
            body {
                font-family:Helvetica, sans-serif;
            }
            ]]>
            </style>
        <xf:model>

            <xf:instance id="save-data">
                <data xmlns="">
                    <zip-code>44526</zip-code>
                </data>
            </xf:instance>
            
            <xf:instance id="zip-check">
                <data xmlns="">
                    <zip-code>44526</zip-code>
                </data>
            </xf:instance>
            
            <!-- place to store the results of a the zip code -->
            <xf:instance id="zip-check-results">
                <data xmlns="">
                    <id/>
                </data>
            </xf:instance>

            
            
            <xf:submission id="zip-check-submission" method="get" action="zip-check.xq"
                ref="instance('zip-check')" replace="instance" instance="zip-check-results"
                separator=";"/>
            
        </xf:model>
    </head>
    <body>

        <xf:input ref="instance('save-data')/zip-code" incremental="true">
            <xf:label>Zip Code:</xf:label>
            <xf:hint>Five digit zip code.</xf:hint>
            <xf:action ev:event="DOMFocusOut">
                <!-- copy the value in the form to the outgoing submission instance -->
                <xf:setvalue ref="instance('zip-check')/zip-code"
                    value="instance('save-data')/zip-code"/>
                <xf:send submission="zip-check-submission"/>
            </xf:action>
        </xf:input>

        <xf:output ref="instance('zip-check-results')/message">
            <xf:label>Response:</xf:label>
        </xf:output>

        <xf:trigger submission="zip-check-submission">
            <xf:label>Check Zip Code</xf:label>
        </xf:trigger>
    </body>
</html>

即使資料集很小或驗證檢查很簡單,也可以使用此技術。表單設計者必須考慮在表單中儲存驗證規則與來回訪問服務的開銷之間的權衡。此模式有幾種變體。一種變體是使用“建議”模式,在使用者輸入資料時建議多個值中的一個。在這種情況下,每個更改的字元都可能觸發新的可能值列表。

華夏公益教科書