※とりあえず"career"という属性を追加したレンダリングを行うのみ
faceletsを使用する場合、独自に作成したJSFカスタムコンポーネントは使用できまんせん。
○やるべきこと
・taglibファイルの作成
・web.xml登録
・カスタムUIコンポーネントクラスの作成
・カスタムレンダラーの作成
・faces-config.xmlにUIコンポーネントとレンダラーの登録
・xhtmlでのカスタムタグ使用
○taglibファイルの作成
カスタムタグをtaglibファイルを作成してWEB-INF直下に配置します。
以下を定義します。
・namespace
・tag-name
・component-type
・renderer-type
○custom.taglib.xml
<?xml version="1.0"?> <!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "http://java.sun.com/dtd/facelet-taglib_1_0.dtd"> <facelet-taglib> <namespace>http://www.arc-mind.com/jsf</namespace> <tag> <tag-name>extLink</tag-name> <component> <component-type>ui.component.ExtLink</component-type> <renderer-type>ui.render.ExtLinkRender</renderer-type> </component> </tag> </facelet-taglib>
○web.xmlに登録
web.xmlに作成したcustom.taglib.xmlを登録します。
web.xmlに以下のcontext-paramを追加。
※faceletsのversionによってparam-nameが違うため、以下のどちらかを指定する。
<context-param> <param-name>javax.faces.FACELETS_LIBRARIES</param-name> <param-value>/WEB-INF/custom.taglib.xml</param-value> </context-param>
※facelets-1.1.15-jsf1.2はこちらの定義で動作
<context-param> <param-name>facelets.LIBRARIES</param-name> <param-value> /WEB-INF/custom.taglib.xml </param-value> </context-param>
○カスタムUIコンポーネントクラスの作成
HtmlCommandLinkクラスを拡張してカスタムUIコンポーネントクラスを作成。
オーバライドするべきメソッドは以下の通り。
getFamily() ファミリ名を返すメソッド
package ui.component; import javax.faces.component.html.HtmlCommandLink; public class ExtLink extends HtmlCommandLink { @Override public String getFamily() { return "GpsLinkFamily"; } }
○faces-config.xmlにUIコンポーネントとレンダラーの登録
<component> <component-type>ui.component.ExtLink</component-type> <component-class>ui.component.ExtLink</component-class> </component> <render-kit> <render-kit-id>HTML_BASIC</render-kit-id> <renderer> <component-family>ExtLinkFamily</component-family> <renderer-type>ui.render.ExtLinkRender</renderer-type> <renderer-class>ui.render.ExtLinkRender</renderer-class> </renderer> </render-kit>
○カスタムレンダラーの作成
必要に応じてdecodeメソッドと各種encodeメソッドをオーバーライド。
decodeメソッドはmanagedBean適用時(ブラウザ→サーバ)。
encodeメソッドはレンダリング時(サーバ→ブラウザ)。
赤字部分のみ追加であとはCommandLinkRendererのコピペ
encode処理にて属性にcareerを追加してみる。decode処理はそのまま。
※ decodeでリクエストパラメータからコンポーネントに設定する場合はsetValue()ではなく、
setSubmittedValue()で値を設定する。valueChangeListener()がsetValueだと呼ばれないため。
package ui.render; import java.io.IOException; import java.util.Map; 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 { public ExtLinkRender() { super(); } 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); } 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("career", "#", 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; } }
○xhtmlでのカスタムタグ使用
taglibファイルに定義したnamespaceでタグを使用する。
<%@ 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>
注意点
JBossToolでSeemプロジェクトを作成するとsrc/hotとsrc/mainが作成されるが、src/main側に入れないとClassが見つからない
と怒られる。
src/hot エンティティクラス以外のソースディレクトリ
src/main エンティティクラスのソースディレクトリ
こんにちは。
返信削除カスタムタグの使い方、勉強になります!