※とりあえず"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 エンティティクラスのソースディレクトリ
こんにちは。
返信削除カスタムタグの使い方、勉強になります!