|
Component可以自己負責將物件資料編碼為HTML文件或其它的輸出文件,也可以將這個任務委託給 Renderer,這邊先介紹的是讓Component自己負責編碼的動作。 這邊著重的是介紹完成自訂元件所必須的流程,所以我們不設計太複雜的元件,這邊將完成以下的元件,這個元件會有一個輸入文字欄位以及一個送出按鈕: ![]() 您要繼承UIComponent或其子類別來自訂Component,由於文字欄位是一個輸入欄位,為了方便,您可以繼承UIInput類別,這可以讓您 省去一些處理細節的功夫,在繼承UIComponent或其子類別後,與編碼相關的主要有三個方法:
其中encodeChildren()是在包括子元件時必須定義,Component如果它的 getRendersChildren()方法傳回true時會呼叫encodeChildren()方法,預設上, getRendersChildren()方法傳回false。 由於我們的自訂元件相當簡單,所以將編碼的動作寫在encodeBegin()或是encodeEnd()都可以,我們這邊是定義encodeBegin ()方法:
package onlyfun.caterpillar; 在encodeBegin()方法中,我們取得ResponseWriter物件,這個物件可以協助您輸出HTML標籤、屬性等,我們使用 getClientId()取得元件的id,這個id是每個元件的唯一識別,預設上如果您沒有指定,則JSF會自動為您產生id值。 接著我們分別對輸入文字欄位及送出鈕作HTML標籤輸出,在輸出時,我們將name屬性設成clientId與一個字串值的結合(即TEXT或CMD),這是為了方便在解碼時,取得對應name屬性的請求值。 在encodeTextField中我們有呼叫getValue()方法,這個方法是從UIOutput繼承下來的,getValue() 方法可以取得Component的設定值,這個值可能是靜態的屬性設定值,也可能是JSF Expression的綁定值,預設會先從元件的屬性設定值開始找尋,如果找不到,再從綁定值(ValueBinding物件)中找尋,元件的屬性值或綁 定值的設定,是在定義Tag時要作的事。 編碥的部份總結來說,是取得Component的值並作適當的HTML標籤輸出,再來我們看看解碼的部份,這是定義在decode()方法中,將下面的內容加入至上面的類別定義中: ....
public void decode(FacesContext context) { Map reqParaMap = context.getExternalContext(). getRequestParameterMap(); String clientId = getClientId(context); String submittedValue = (String) reqParaMap.get(clientId + TEXT); setSubmittedValue(submittedValue); setValid(true); } .... 我們必須先取得RequestParameterMap,這個Map物件中填入了所有客戶端傳來的請求參數, Component在這個方法中有機會查詢這些請求參數中,是否有自己所想要取得的資料,記得我們之前解碼時,是將輸入欄位的name屬性解碼為 client id加上一個字串值(即TEXT設定的值),所以這時,我們嘗試從RequestParameterMap中取得這個請求值。 取得請求值之後,您可以將資料藉由setSumittedValue()設定給綁定的bean,最後呼叫setValid()方法,這個方法設定為 true時,表示元件正確的獲得自己的值,沒有任何的錯誤發生。 由於我們先不使用Renderer,所以在建構函式中,我們設定RendererType為null,表示我們不使用Renderer進行解碼輸出: public UITextWithCmd() {
setRendererType(null); } 在我們的例子中,我們都是處理字串物件,所以這邊不需要轉換器,如果您需要使用轉換器,可以呼叫setConverter()方法加以設定,在不使用 Renderer的時候,Component要設定轉換器來自行進行字串與物件的轉換。 |