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