※とりあえず"test"という属性を追加したレンダリングを行うのみ
やるべきこと
・カスタムタグクラスの作成
・カスタムUIコンポーネントクラスの作成
・カスタムレンダラーの作成
・tldファイルの作成 (タグクラスの登録とプロパティの追加)
・faces-config.xmlにUIコンポーネントとレンダラーの登録
・tldファイルの配置
・jspでのカスタムタグ使用
○カスタムタグクラスの作成
CommandLinkTagクラスを拡張してカスタムタグクラスを作成。
オーバライドするべきメソッドは以下の通り。
getRendererType() レンダラタイプを返すメソッド
getComponentType() コンポーネントタイプを返すメソッド
setProperties() JSPページに指定された属性値を、UIコンポーネントに設定するメソッド
package ui.tag; import java.util.Map; import javax.faces.component.UIComponent; import com.sun.faces.taglib.html_basic.CommandLinkTag; public class ExtLinkTag extends CommandLinkTag { private String test; public void setTest(String test) { this.test = test; } @Override public String getRendererType() { return "ExtLinkRenderer"; } @Override public String getComponentType() { return "ExtLink"; } @Override protected void setProperties(UIComponent component) { super.setProperties(component); MapattributeMap = component.getAttributes(); if (test != null) { attributeMap.put("test", test); } }
○カスタムUIコンポーネントクラスの作成
HtmlCommandLinkクラスを拡張してカスタムUIコンポーネントクラスを作成。
オーバライドするべきメソッドは以下の通り。
getFamily() ファミリ名を返すメソッド
package ui.component; import javax.faces.component.html.HtmlCommandLink; public class ExtLink extends HtmlCommandLink { @Override public String getFamily() { return "ExtLinkFamily"; } }
○tldファイルの作成
タグクラスの登録とプロパティの追加を行う。
・・・ <tag> <name> extlink </name> <tag-class> ui.tag.ExtLinkTag </tag-class> <body-content> JSP </body-content> <attribute> <name> action </name> <required> false </required> <deferred-method> <method-signature> java.lang.Object action() </method-signature> </deferred-method> </attribute> <attribute> <name> actionListener </name> <required> false </required> <deferred-method> <method-signature> void actionListener(javax.faces.event.ActionEvent) </method-signature> </deferred-method> </attribute> <attribute> <name> id </name> <required> false </required> <rtexprvalue> true </rtexprvalue> </attribute> <attribute> <name> test </name> <required> false </required> <rtexprvalue> true </rtexprvalue> </attribute> ・・・
○faces-config.xmlにUIコンポーネントとレンダラーの登録
<component> <component-type>ExtLink</component-type> <component-class>ui.component.ExtLink</component-class> </component> <render-kit> <renderer> <component-family>ExtLinkFamily</component-family> <renderer-type>ExtLinkRenderer</renderer-type> <renderer-class>ui.render.ExtLinkRender</renderer-class> </renderer> </render-kit>
○カスタムレンダラーの作成
必要に応じてdecodeメソッドと各種encodeメソッドをオーバーライド。
decodeメソッドはmanagedBean適用時。
encodeメソッドはレンダリング時。
encode処理にて属性にtestを追加してみる。
decode処理はそのまま。
package ui.render; import java.io.IOException; import java.util.Map; import java.util.logging.Level; import javax.faces.component.UIComponent; import javax.faces.component.UIForm; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import com.sun.faces.renderkit.AttributeManager; import com.sun.faces.renderkit.RenderKitUtils; import com.sun.faces.renderkit.html_basic.CommandLinkRenderer; import com.sun.faces.renderkit.html_basic.HtmlBasicRenderer; public class ExtLinkRender extends CommandLinkRenderer { private static final String ATTRIBUTES[]; private static final String SCRIPT_STATE = "com.sun.faces.scriptState"; static { ATTRIBUTES = AttributeManager.getAttributes(com.sun.faces.renderkit.AttributeManager.Key.COMMANDLINK); } @Override public void decode(FacesContext context, UIComponent component) { super.decode(context, component); } @Override public void encodeBegin(FacesContext context, UIComponent component) throws IOException { rendererParamsNotNull(context, component); if (!shouldEncode(component)) return; boolean componentDisabled = Boolean.TRUE.equals(component .getAttributes().get("disabled")); String formClientId = getFormClientId(component, context); if (formClientId == null && logger.isLoggable(Level.WARNING)) logger.log(Level.WARNING, Component {0} must be enclosed inside a form, component .getId()); if (componentDisabled || formClientId == null) { renderAsDisabled(context, component); } else { if (!hasScriptBeenRendered(context)) { RenderKitUtils.renderFormInitScript( context.getResponseWriter(), context); setScriptAsRendered(context); } renderAsActive(context, component); } } protected void renderAsActive(FacesContext context, UIComponent command) throws IOException { ResponseWriter writer = context.getResponseWriter(); if (writer == null) throw new AssertionError(); String formClientId = getFormClientId(command, context); if (formClientId == null) return; writer.startElement("a", command); writeIdAttributeIfNecessary(context, writer, command); writer.writeAttribute("href", "#", "href"); Map attributeMap = command.getAttributes(); writer.writeAttribute("test", "#", null); RenderKitUtils.renderPassThruAttributes(writer, command, ATTRIBUTES); RenderKitUtils.renderXHTMLStyleBooleanAttributes(writer, command); String userOnclick = (String) command.getAttributes().get("onclick"); StringBuffer sb = new StringBuffer(128); boolean userSpecifiedOnclick = userOnclick != null && !"".equals(userOnclick); if (userSpecifiedOnclick) { sb.append("var a=function(){"); userOnclick = userOnclick.trim(); sb.append(userOnclick); if (userOnclick.charAt(userOnclick.length() - 1) != ';') sb.append(';'); sb.append("};var b=function(){"); } HtmlBasicRenderer.Param params[] = getParamList(command); String commandClientId = command.getClientId(context); String target = (String) command.getAttributes().get("target"); if (target != null) target = target.trim(); else target = ""; sb.append(getOnClickScript(formClientId, commandClientId, target, params)); if (userSpecifiedOnclick) sb.append("};return (a()==false) ? false : b();"); writer.writeAttribute("onclick", sb.toString(), "onclick"); writeCommonLinkAttributes(writer, command); writeValue(command, writer); writer.flush(); } private static boolean hasScriptBeenRendered(FacesContext context) { return context.getExternalContext().getRequestMap().get( com.sun.faces.scriptState) != null; } private static void setScriptAsRendered(FacesContext context) { context.getExternalContext().getRequestMap().put( com.sun.faces.scriptState, Boolean.TRUE); } private static String getFormClientId(UIComponent component, FacesContext context) { UIForm form = getMyForm(component); if (form != null) return form.getClientId(context); else return null; } private static UIForm getMyForm(UIComponent component) { UIComponent parent; for (parent = component.getParent(); parent != null && !(parent instanceof UIForm); parent = parent.getParent()) ; return (UIForm) parent; } }
○tldファイルの配置
WEB-INF/jsf_custum.tldに配置 jsf-tlds.jarに含めてもよいと思います。
○jspでのカスタムタグ使用
taglibでtldファイル読込みとprefix定義を行う。
タグ名はtldファイルに定義したname
<%@ page contentType="text/html;charset=Shift_JIS" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="/WEB-INF/jsf_custum.tld" prefix="custom" %> <html> <head> <title>HelloWorld</title> </head> <body> <f:view> <h:form> 文字を入力して下さい:<h:inputText id="string" value="#{HelloWorldBean.helloWorld}"/> <h:commandButton value="送信"/> <p><h:outputText id="output" value="#{HelloWorldBean.helloWorld}"/></p> <h:commandButton id="btn1" action="ok" value="遷移" actionListener="#{HelloWorldBean.assembleMessage}" /> <br> <custom:extlink id="link1" action="ok" actionListener="#{HelloWorldBean.assembleMessage}">カスタムリンク</custom:extlink> </h:form> </f:view> </body> </html>
0 件のコメント:
コメントを投稿