web-dev-qa-db-ja.com

動的JSFフォームフィールドを作成する方法

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のサブクラスが必要です」のような答えは好みません。

21
Shervin Asgari

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>

JsfXmlFilterFacesServlet<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.xhtmlpersons.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キーfield1field2field3などで利用できます。

17
BalusC