2

JSF 2 を使用してカスタム複合コンポーネントを構築しようとしています。このコンポーネント内に、フォームを送信するときに表示したいダイアログがありますが、appendToBody="false" を使用するとダイアログが表示されず、私は appendToBody="true" を使用します。

私の検索コンポーネントは次のようになります。

ここに画像の説明を入力

ユーザーが inputText に何らかの値を入力して検索ボタンを押すと、次のようなダイアログが表示されます。

ここに画像の説明を入力

これを機能させる唯一の方法は、コンポーネントに 1 つではなく 2 つのボタンを配置することです。1 つは値を送信するため、もう 1 つはダイアログを表示するためです。これは、appendToBody="false" プロパティを指定してダイアログを使用する場合です。したがって、私のテスト コンポーネントは次のようになります。

ここに画像の説明を入力

appendToBody="true" でダイアログを使用すると、ダイアログを一度に送信して表示できますが、ダイアログを閉じることができないなど、ダイアログには他の問題があります。データが更新されない など

これが私のコードです(lov.xhtml):

<ui:component xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui"
    xmlns:composite="http://java.sun.com/jsf/composite">

    <composite:interface componentType="lov">
        <composite:attribute name="value" required="true" />
        <composite:attribute name="definitionFile" required="true" />
        <composite:attribute name="definitionName" required="true" />
    </composite:interface>

    <composite:implementation>
        <h:outputStylesheet library="css" name="styles.css" />
        <p:inputText id="lovInputText" styleClass="lovInputText"
            value="#{cc.selectedValue}" binding="#{cc.lovInputText}" />
        <p:commandButton styleClass="lovButton" icon="ui-icon-search"
            onclick="searchAndSelect.show();" actionListener="#{cc.updateDialog}"
            update="@form" />
        <p:commandButton value="Open" icon="ui-icon-search"
            onclick="searchAndSelect.show();" />
        <h:outputLabel id="outputLabel" value="#{cc.selectedValue}" />
        <p:dialog id="searchAndSelectDialog" header="Search and Select"
            appendToBody="false" closable="false" resizable="false"
            widgetVar="searchAndSelect" showEffect="fade" hideEffect="fade"
            binding="#{cc.searchAndSelectDialog}">
            <p:panelGrid>
                <p:row>
                    <p:column>
                        <h:outputLabel value="Value: " />
                    </p:column>
                    <p:column>
                        <h:form id="sasInputTextForm" prependId="true">
                            <p:inputText id="sasInputText" value="#{cc.selectedValue}"
                                label="Value" binding="#{cc.sasInputText}" />
                        </h:form>
                    </p:column>
                </p:row>
                <p:row>
                    <p:column colspan="2" styleClass="searchAndResetColumn">
                        <h:form>
                            <p:commandButton value="Search" icon="ui-icon-search"
                                actionListener="#{cc.search}" />
                            <p:commandButton type="button" value="Reset"
                                icon="ui-icon-arrowrefresh-1-e" />
                        </h:form>
                    </p:column>
                </p:row>
                <p:row>
                    <p:column colspan="2">
                        <h:form>
                            <p:dataTable var="item" value="#{cc.data}">
                                <p:columns value="#{cc.columns}" var="column"
                                    columnIndexVar="colIndex" sortBy="#{item[column.property]}"
                                    filterBy="#{item[column.property]}">
                                    <f:facet name="header">#{column.header}</f:facet>  
                            #{item[column.property]}
                        </p:columns>
                            </p:dataTable>
                        </h:form>
                    </p:column>
                </p:row>
            </p:panelGrid>
            <f:facet name="footer">
                <p:commandButton type="button" value="OK" icon="ui-icon-check" />
                <p:commandButton type="button" value="Cancel" icon="ui-icon-cancel"
                    onclick="searchAndSelect.hide();" />
            </f:facet>
        </p:dialog>
    </composite:implementation>
</ui:component>

コンポーネント バッキング Bean (Lov.java) は次のとおりです。

@FacesComponent("lov")
public class Lov extends UIInput implements NamingContainer {

    private List<ColumnModel> columns = new ArrayList<ColumnModel>();

    private String definitionFile;

    private String definitionName;

    private String bean;

    private String attribute;

    private List<String> displayAttributes;

    private UIInput lovInputText;

    private UIInput sasInputText;

    private UIComponent searchAndSelectDialog;

    // Fields
    // -------------------------------------------------------------------------------------

    // Actions
    // ------------------------------------------------------------------------------------

    /**
     * Returns the component family of {@link UINamingContainer}. (that's just
     * required by composite component)
     */
    @Override
    public String getFamily() {
        return UINamingContainer.COMPONENT_FAMILY;
    }

    /**
     * Set the selected and available values of the day, month and year fields
     * based on the model.
     */
    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        System.out.println("Called encodeBeing method...");
        System.out.println("getValue: "+ getValue().toString());
        setSelectedValue(getValue().toString());
        definitionFile = getAttributeValue("definitionFile", null);
        definitionName = getAttributeValue("definitionName", null);

        try {
            parseXml();
            queryData();
        } catch (Exception e) {
            e.printStackTrace();
        }

        createDynamicColumns();

        super.encodeBegin(context);
    }

    /**
     * Returns the submitted value in dd-MM-yyyy format.
     */
    @Override
    public Object getSubmittedValue() {
        System.out.println("====================================================");
        System.out.println("getSubmittedValue method called...");
        System.out.println("submittedValue: " + lovInputText.getSubmittedValue());
        System.out.println("localValue: " +lovInputText.getLocalValue());
        return lovInputText.getSubmittedValue();
    }

    /**
     * Converts the submitted value to concrete {@link Date} instance.
     */
    @Override
    protected Object getConvertedValue(FacesContext context,
            Object submittedValue) {
        return super.getConvertedValue(context, submittedValue);
    }

    public void search(ActionEvent actionEvent) {
        System.out.println("Search method called...");
        try {
            queryData();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Update the available days based on the selected month and year, if necessary.
     */
    public void updateDialog(ActionEvent actionEvent) {
        System.out.println("==========================================================");
        System.out.println("updateDialog method called...");
        System.out.println("getValue: "+getValue().toString());
        setSelectedValue(getValue().toString());
        /*FacesContext context = FacesContext.getCurrentInstance(); // Update dialog
        context.getPartialViewContext().getRenderIds().add(searchAndSelectDialog.getClientId(context));*/
    }

    // Helpers
    // ------------------------------------------------------------------------------------

    /**
     * Return specified attribute value or otherwise the specified default if
     * it's null.
     */
    @SuppressWarnings("unchecked")
    private <T> T getAttributeValue(String key, T defaultValue) {
        T value = (T) getAttributes().get(key);
        return (value != null) ? value : defaultValue;
    }

    /**
     * Create an integer array with values from specified begin to specified
     * end, inclusive.
     */
    private static Integer[] createIntegerArray(int begin, int end) {
        int direction = (begin < end) ? 1 : (begin > end) ? -1 : 0;
        int size = Math.abs(end - begin) + 1;
        Integer[] array = new Integer[size];

        for (int i = 0; i < size; i++) {
            array[i] = begin + (i * direction);
        }

        return array;
    }

    protected void parseXml() throws ParserConfigurationException,
            SAXException, IOException, XPathExpressionException,
            URISyntaxException {
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        dbFactory.setNamespaceAware(true);
        DocumentBuilder builder = dbFactory.newDocumentBuilder();
        ServletContext servletContext = (ServletContext) FacesContext
                .getCurrentInstance().getExternalContext().getContext();
        InputStream is = servletContext.getResourceAsStream(definitionFile);
        Document doc = builder.parse(is);
        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();

        XPathExpression expr = xpath.compile(String.format(
                "/definitions/definition[@name='%s']/bean/@name",
                definitionName));
        Object result = expr.evaluate(doc, XPathConstants.STRING);
        bean = result.toString();
        setBean(bean);
        System.out.println("bean: " + bean);

        expr = xpath
                .compile(String
                        .format("/definitions/definition[@name='%s']/attributes/attribute/@name",
                                definitionName));
        result = expr.evaluate(doc, XPathConstants.STRING);
        attribute = result.toString();
        setAttribute(attribute);
        System.out.println("attribute: " + attribute);

        expr = xpath
                .compile(String
                        .format("/definitions/definition[@name='%s']/displayAttributes/attribute",
                                definitionName));
        result = expr.evaluate(doc, XPathConstants.NODESET);
        displayAttributes = new ArrayList<String>();
        NodeList nodes = (NodeList) result;
        for (int i = 0; i < nodes.getLength(); i++) {
            NamedNodeMap attrs = nodes.item(i).getAttributes();
            for (int j = 0; j < attrs.getLength(); j++) {
                String nodeName = attrs.item(j).getNodeName();
                if (nodeName.equalsIgnoreCase("name")) {
                    displayAttributes.add(attrs.item(j).getNodeValue());
                }
            }
        }
        setDisplayAttributes(displayAttributes);
        System.out.println("displayAttributes: " + displayAttributes.toString());
    }

    protected void queryData() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException {
        FilterableBean bean = (FilterableBean) findBean(getBean());
        if (lovInputText != null) {
            System.out.println("lovInputText exists");
        }
        System.out.println("queryData value: "+getValue().toString());
        setData(bean.get(getSelectedValue()));
        System.out.println("data: "+ getData().toString());
    }

    @SuppressWarnings("unchecked")
    public static <T> T findBean(String beanName) {
        FacesContext context = FacesContext.getCurrentInstance();
        return (T) context.getApplication().evaluateExpressionGet(context, "#{" + beanName + "}", Object.class);
    }

    protected void createDynamicColumns() {
        if (displayAttributes != null) {
            columns.clear();

            for (String displayAttribute : displayAttributes) {
                String key = displayAttribute.trim();
                columns.add(new ColumnModel(key.toUpperCase(), key));
            }
        }
    }

    // Getters/setters
    // ----------------------------------------------------------------------------

    @SuppressWarnings("rawtypes")
    public List getData() {
        return (List) getStateHelper().get("data");
    }

    @SuppressWarnings("rawtypes")
    public void setData(List data) {
        getStateHelper().put("data", data);
    }

    private String hello = "hello";

    public String getHello() {
        return hello;
    }

    public void setHello(String hello) {
        this.hello = hello;
    }

    public List<ColumnModel> getColumns() {
        return columns;
    }

    public String getSelectedValue() {
        return (String) getStateHelper().get("selectedValue");
    }

    public void setSelectedValue(String selectedValue) {
        getStateHelper().put("selectedValue", selectedValue);
    }

    public UIInput getLovInputText() {
        return lovInputText;
    }

    public void setLovInputText(UIInput lovInputText) {
        this.lovInputText = lovInputText;
    }

    public UIInput getSasInputText() {
        return sasInputText;
    }

    public void setSasInputText(UIInput sasInputText) {
        this.sasInputText = sasInputText;
    }

    public UIComponent getSearchAndSelectDialog() {
        return searchAndSelectDialog;
    }

    public void setSearchAndSelectDialog(UIComponent searchAndSelectDialog) {
        this.searchAndSelectDialog = searchAndSelectDialog;
    }

    public String getBean() {
        return (String) getStateHelper().get("bean");
    }

    public void setBean(String bean) {
        getStateHelper().put("bean", bean);
    }

    public String getAttribute() {
        return (String) getStateHelper().get("attribute");
    }

    public void setAttribute(String attribute) {
        getStateHelper().put("attribute", attribute);
    }

    @SuppressWarnings("unchecked")
    public List<String> getDisplayAttributes() {
        return (List<String>) getStateHelper().get("displayAttributes");
    }

    public void setDisplayAttributes(List<String> displayAttributes) {
        getStateHelper().put("displayAttributes", displayAttributes);
    }

    static public class ColumnModel implements Serializable {

        private String header;
        private String property;

        public ColumnModel(String header, String property) {
            this.header = header;
            this.property = property;
        }

        public String getHeader() {
            return header;
        }

        public String getProperty() {
            return property;
        }
    }
}

コンポーネントの使用方法は次のとおりです。

<h:form>
  <my:lov value="#{testBean.region}" definitionFile="/resources/xml/lov/definitions/country.xml" definitionName="LOV_Region"/>
  <p:messages />
</h:form>

BalusC の記事に従って、このコンポーネントを作成しました。リンクは次のとおりです。

値で更新され、一度に表示されるカスタム複合コンポーネントでダイアログを使用するにはどうすればよいですか?

4

1 に答える 1