this oneのようないくつかの同様の質問を見つけましたが、これを行うには多くの方法があるため、混乱しました。
読み取り中のXML
ファイルを取得しています。このXML
には、表示する必要があるいくつかのフォームフィールドに関する情報が含まれています。
そこで、必要なすべての情報を含むこのカスタムDynamicField.Java
を作成しました。
public class DynamicField {
private String label; // label of the field
private String fieldKey; // some key to identify the field
private String fieldValue; // the value of field
private String type; // can be input,radio,selectbox etc
// Getters + setters.
}
したがって、List<DynamicField>
があります。
このリストを繰り返し処理し、フォームフィールドに値を入力して、次のようにします。
<h:dataTable value="#{dynamicFields}" var="field">
<my:someCustomComponent value="#{field}" />
</h:dataTable>
<my:someCustomComponent>
は、適切なJSFフォームコンポーネント(つまり、label、inputText)を返します。
もう1つのアプローチは、<my:someCustomComponent>
を表示するだけで、フォーム要素とともにHtmlDataTable
を返すことです。 (私はこれがおそらくもっと簡単だと思います)。
どのアプローチが最適ですか?誰かが私にこれをどのように作成できるかを示すいくつかのリンクまたはコードを私に示すことができますか?私は完全なコード例を好んでおり、「javax.faces.component.UIComponent
のサブクラスが必要です」のような答えは好みません。
OriginがXMLの場合、まったく異なるアプローチをとることをお勧めします: [〜#〜] xsl [〜#〜] 。 FaceletsはXHTMLベースです。 XSLを使用して、XMLからXHTMLに簡単に移行できます。これは、JSFが機能する前に起動する少しまともなFilter
で実行できます。
こちらがキックオフの例です。
persons.xml
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person>
<name>one</name>
<age>1</age>
</person>
<person>
<name>two</name>
<age>2</age>
</person>
<person>
<name>three</name>
<age>3</age>
</person>
</persons>
persons.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:f="http://Java.Sun.com/jsf/core"
xmlns:h="http://Java.Sun.com/jsf/html">
<xsl:output method="xml"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
<xsl:template match="persons">
<html>
<f:view>
<head><title>Persons</title></head>
<body>
<h:panelGrid columns="2">
<xsl:for-each select="person">
<xsl:variable name="name"><xsl:value-of select="name" /></xsl:variable>
<xsl:variable name="age"><xsl:value-of select="age" /></xsl:variable>
<h:outputText value="{$name}" />
<h:outputText value="{$age}" />
</xsl:for-each>
</h:panelGrid>
</body>
</f:view>
</html>
</xsl:template>
</xsl:stylesheet>
JsfXmlFilter
はFacesServlet
の<servlet-name>
にマッピングされており、FacesServlet
自体が<url-pattern>
の*.jsf
にマッピングされていると想定しています。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest r = (HttpServletRequest) request;
String rootPath = r.getSession().getServletContext().getRealPath("/");
String uri = r.getRequestURI();
String xhtmlFileName = uri.substring(uri.lastIndexOf("/")).replaceAll("jsf$", "xhtml"); // Change this if FacesServlet is not mapped on `*.jsf`.
File xhtmlFile = new File(rootPath, xhtmlFileName);
if (!xhtmlFile.exists()) { // Do your caching job.
String xmlFileName = xhtmlFileName.replaceAll("xhtml$", "xml");
String xslFileName = xhtmlFileName.replaceAll("xhtml$", "xsl");
File xmlFile = new File(rootPath, xmlFileName);
File xslFile = new File(rootPath, xslFileName);
Source xmlSource = new StreamSource(xmlFile);
Source xslSource = new StreamSource(xslFile);
Result xhtmlResult = new StreamResult(xhtmlFile);
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer(xslSource);
transformer.transform(xmlSource, xhtmlResult);
} catch (TransformerException e) {
throw new RuntimeException("Transforming failed.", e);
}
}
chain.doFilter(request, response);
}
http://example.com/context/persons.jsf で実行すると、このフィルタはpersons.xml
を使用してpersons.xhtml
をpersons.xsl
に変換し、最後に配置しますpersons.xhtml
JSFが期待する場所にあります。
確かに、XSLには多少の学習曲線がありますが、ソースはXMLであり、宛先はXMLベースのwelであるため、IMOはジョブに適したツールです。
フォームとマネージドBeanの間のマッピングを行うには、Map<String, Object>
を使用するだけです。このように入力フィールドに名前を付けると
<h:inputText value="#{bean.map.field1}" />
<h:inputText value="#{bean.map.field2}" />
<h:inputText value="#{bean.map.field3}" />
...
送信された値は、Map
キーfield1
、field2
、field3
などで利用できます。