本節將實現一個HtmlInput tag,仍然是Noncomposite Component。接受用戶的輸入,點擊按鈕後,會顯示用戶輸入的信息。有朋友要看效果圖,我也想show一下,可是圖片上傳失敗。在這個系列文章結束的時候,我會上傳我的代碼。
基本流程是,用戶在初始頁面上輸入數據,點擊按鈕後,一般采用PostBack的方法將數據傳遞到JSF的 Serverlet,在後臺的Renderer的decode方法內部通過 FacesContext.getExternalContext().getRequestParameterMap()獲取Map對象,然後通過 key去查找用戶的輸入數據。key是什麼?這裡采用clientIdValue:InputField的格式。
需要解釋一下ClientId,JSF定義瞭一個規則,為瞭知道是哪一個Tag,程序員可以通過下面的方法在頁面初始化的時候輸出ClientId到客戶端:(實際上一般都是賦給瞭HTML tag的 name屬性)
writer.writeAttribute(“name”, clientIdValue, “clientId”);//第三個參數必須是”clientId”,是JSF內部使用的。
然後當客戶端提交數據後,UIComponent可以通過調用成員函數getClientId(context)獲得這個clientIdValue。在我這個例子裡面,我在頁面初始化的時候將從調用component.getClientId()或得clientIdValue並輸出到客戶端,用來標志我的HtmlInput tag,然後在下次客戶提交的時候拿回來。但是由於我的HtmlInput tag內部有三個子tag,一個輸入,一個按鈕,一個輸出,對於前兩個,也需要ClientId標志它們,我使用瞭父ClientIdValue+區分字符+子tag名稱的做法。默認區分字符是:。因此,當獲取到HtmlInput tag的ClientId後,拼接出輸入子tag的ClientId:”ClientIdValue:InputField”,將其作為key從map中檢索用戶填入的數據。所以ClientId對於檢索輸入數據非常重要,要想能檢索到,你必須按照JSF的規則先在初始化的時候給需要的tag設置ClientId,以後才能拿回來作為key從Map中使用。
區分字符是可以修改的,通過在web.xml文件中配置 context-param下的javax.faces.SEPARATOR_CHAR.這個以後用到CSS的時候再說。
現在秀一下代碼,Renderer的代碼:
package com.freebird.renderer;
import com.freebird.component.HtmlInput;
import javax.faces.render.Renderer;
import javax.faces.context.ResponseWriter;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.component.UINamingContainer;
import java.util.Map;
/**
* Describe class HtmlInputRenderer here.
*
*
* Created: Wed Dec 29 12:14:24 2010
*
* @author <a href=”chenshumailto:chenshu@csdesktop”>chenshu</a>
* @version 1.0
/
public class HtmlInputRenderer extends Renderer {
public void decode(FacesContext context, UIComponent component) {
Map requestMap = context.getExternalContext().getRequestParameterMap();
String clientId = component.getClientId(context);
char sep = UINamingContainer.getSeparatorChar(context);
String symbol = ((String) requestMap.get(clientId + sep + “inputfield”));
HtmlInput myComponent = (HtmlInput)component;
myComponent.setSubmittedValue(symbol);
}
@Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
String clientId = component.getClientId(context);
char sep = UINamingContainer.getSeparatorChar(context);
encodeInputField(context, clientId + sep + “inputfield”,component);
encodeSubmitButton(context, clientId + sep + “submit”,component);
encodeOutputField(context,component);
}
private void encodeInputField(FacesContext context, String clientId, UIComponent component) throws IOException {
// Render a standard HTML input field
ResponseWriter writer = context.getResponseWriter();
writer.startElement(“input”, component);
writer.writeAttribute(“type”, “text”, null);
writer.writeAttribute(“name”, clientId, “clientId”);
HtmlInput myComponent = (HtmlInput)component;
String value = (String)myComponent.getSubmittedValue();
if (value != null) {
writer.writeAttribute(“value”, value, “value”);
}
writer.writeAttribute(“size”, “6”, null);
writer.endElement(“input”);
}
private void encodeSubmitButton(FacesContext context, String clientId , UIComponent component) throws IOException {
// render a submit button
ResponseWriter writer = context.getResponseWriter();
writer.startElement(“input”, component);
writer.writeAttribute(“type”, “Submit”, null);
writer.writeAttribute(“name”, clientId, “clientId”);
writer.writeAttribute(“value”, “Click Me!”, null);
writer.endElement(“input”);
}
private void encodeOutputField(FacesContext context,UIComponent component) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String hellomsg = (String) component.getAttributes().get(“value”);
writer.startElement(“p”, component);
writer.writeText(“You entered: ” + hellomsg, null);
writer.endElement(“p”);
}
}
UIComponent的代碼,HtmlInput類僅僅繼承瞭UIInput類,所以自然擁有瞭getFamily,get/setSubmittedValue方法的實現。
package com.freebird.component;
import javax.faces.component.UIInput;
/*
* Describe class HtmlInput here.
*
*
* Created: Wed Dec 29 11:43:18 2010
*
* @author <a href=”chenshumailto:chenshu@csdesktop”>chenshu</a>
* @version 1.0
/
public class HtmlInput extends UIInput {
}
現在看一下兩個配置文件:
faces-config.xml中添加
<component>
<component-type>HtmlInput</component-type>
<component-class>com.freebird.component.HtmlInput</component-class>
</component>
<render-kit>
<renderer>
<component-family>javax.faces.Input</component-family>
<renderer-type>HtmlInputRenderer</renderer-type>
<renderer-class>com.freebird.renderer.HtmlInputRenderer</renderer-class>
</renderer>
</render-kit>
helloworld.taglib.xml中添加
<tag>
<tag-name>htmlinput</tag-name>
<component>
<component-type>HtmlInput</component-type>
<renderer-type>HtmlInputRenderer</renderer-type>
</component>
</tag>
在web應用程序中使用該tag很簡單,僅僅是一行:
<cs:htmlinput/>