Динамическое добавление полей в форму JSF - PullRequest
4 голосов
/ 01 сентября 2011

У меня есть следующая ситуация, с которой я бы хотел разобраться в JSF. Моя форма состоит из информации о семье (имя / адрес / телефон) и информации о детях. Поскольку в семье может быть более одного ребенка, мне нужно разрешить человеку нажимать кнопку «добавить больше детей», и появится другой раздел «раздел».

Вот простой тестовый пример, который я бросил вместе.

бэк. В семье есть список детей.

@ViewScoped
@ManagedBean
public class TestBackingBean implements Serializable {
    private Family f = new Family();
    private Child childToRemove;

    public TestBackingBean() {
        f.addChild(new Child());
    }

    public Family getFamily() {
        return f;
    }

    public void setChildToRemove(Child childToRemove) {
        this.childToRemove = childToRemove;
    }

    public TimeZone getTimezone() {
        return TimeZone.getDefault();
    }

    public List<Child> getChildren() {
        return f.getChildrenAsList();
    }

    public Child getChildToRemove() {
        return childToRemove;
    }

    public void addChild() {
        f.addChild(new Child());
    }

    public void removeChild() {
        f.removeChild(childToRemove);
    }

}

Вот страница JSF:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich"
    xmlns:h="http://java.sun.com/jsf/html">

<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title><ui:insert name="title" />
    </title>
    <link rel="stylesheet" type="text/css" href="/hcbb/css/main.css" />
</h:head>

<h:body>

    <h:form>

        <h:panelGroup id="parentSection">
            <h:outputLabel value="Parent Name" for="parent_firstName" />
            <h:inputText id="parent_firstName" requiredMessage="Required"
                immediate="true" label="Parent First Name"
                value="#{testBackingBean.family.firstName}">
                <f:validateRequired />
            </h:inputText>
            <rich:message id="parent_firstNameMessage" for="parent_firstName" />
        </h:panelGroup>


        <h:panelGroup id="childrenSection">

            <h:dataTable value="#{testBackingBean.children}" var="child">

                <h:column>
                    <h:panelGrid id="childPanel" columns="3"
                        style="border:1px solid brown; padding: 5px; margin-bottom:5px; width: 600px;">
                        <h:outputText id="childTitle" value="Child"
                            style="font-weight: bold;" />
                        <h:outputText id="spacer" />
                        <a4j:commandButton id="removeBtn"
                            action="#{testBackingBean.removeChild}" immediate="true"
                            value="Remove Child" render="childrenSection"
                            style="float:right;" title="Remove">
                            <f:setPropertyActionListener
                                target="#{testBackingBean.childToRemove}" value="#{child}" />
                        </a4j:commandButton>

                        <h:outputLabel id="child_firstNameLbl" value="First Name" />
                        <h:inputText id="child_firstName" requiredMessage="Required"
                            immediate="true" label="Child First Name"
                            value="#{child.firstName}">
                            <f:validateRequired />
                        </h:inputText>
                        <rich:message id="child_firstNameMessage" for="child_firstName" />

                        <h:outputLabel id="child_lastNameLbl" value="Last Name" />
                        <h:inputText id="child_lastName" requiredMessage="Required"
                            immediate="true" label="Child Last Name"
                            value="#{child.lastName}">
                            <f:validateRequired />
                        </h:inputText>
                        <rich:message id="child_lastNameMessage" for="child_lastName" />

                        <h:outputLabel id="child_dobLbl" value="Birth Date" />
                        <h:inputText id="child_dob" label="Child Birth Date"
                            immediate="true" requiredMessage="Required"
                            value="#{child.dateOfBirth}">
                            <f:convertDateTime id="dobConverter" pattern="MM/dd/yyyy"
                                timeZone="#{testBackingBean.timezone}" />
                            <f:validateRequired />
                        </h:inputText>
                        <rich:message id="child_dobNameMessage" for="child_dob" />
                    </h:panelGrid>
                </h:column>
            </h:dataTable>

            <a4j:commandLink id="addChildBtn" immediate="true"
                render="childrenSection" action="#{testBackingBean.addChild}"
                value="Add Another Child">
            </a4j:commandLink>

        </h:panelGroup>
    </h:form>
</h:body>
</html>

Проблема заключается в сохранении значений при добавлении / удалении дочерних разделов. Если вы введете имя родителя, а затем имя ребенка и дату рождения, а затем нажмите кнопку Добавить, поля для только что добавленного ребенка исчезнут? Я бы подумал, что на кнопке немедленный = true, и поля будут проходить через них.

Проблема заключается в добавлении имени родителя, введите информацию о ребенке и нажмите кнопку «Добавить еще одного ребенка», и только что введенная вами дочерняя информация будет удалена.

Любые предложения о том, как я мог бы заставить все это работать. Похоже на довольно простой и несколько стандартный вариант использования.

Спасибо!

1 Ответ

6 голосов
/ 01 сентября 2011

На первый взгляд выглядит хорошо. Симптомы проблемы сводятся к тому, что f.getChildrenAsList() не возвращает список с новым дочерним элементом, в то время как JSF собирается применить значения запроса. Возможно, этот метод повторно загружает список из БД после отправки? Добавьте точку останова, чтобы изучить ее значение повторной настройки. Или, возможно, область видимости вышла из строя и заставила bean-компонент реконструироваться? Добавьте точку останова в конструктор бина. Его не следует реконструировать, когда вы отправляете форму в том же виде.

Что касается использования атрибута immediate, то все, что вы используете их, совершенно излишне. Просто удали их. Чтобы лучше понять его использование, ознакомьтесь со статьей Debug JSF жизненный цикл (правда, она нацелена на JSF 1.2, но принципы те же для JSF2), а затем прочитайте, в частности, это резюме:

Хорошо, когда я должен использовать непосредственный атрибут?

Если это еще не совсем понятно, вот краткое изложение с примерами использования в реальном мире, когда они могут быть полезны:

  • Если установлено только в UIInput (s), этап проверки процесса будет проходить в фазе применения значений запроса. Используйте это, чтобы установить приоритетность проверки для UIInput рассматриваемого компонента (ов). Если проверка или преобразование не удалась для любого из них, не немедленные компоненты не будут проверены / преобразованы.

  • Если установлено только в UICommand, фаза применения значений запроса до тех пор, пока с обновленными значениями модели фазы не будут пропущены для любого из UIInput компонентов. Используйте это, чтобы пропустить всю обработку формы. Например. Кнопка «Отмена» или «Назад».

  • Если установлено в обоих компонентах UIInput и UICommand, фаза применения значений запроса до тех пор, пока не будут обновлены фазы значений модели, будет пропущена для любого из компонентов UIInput, у которых нет этого атрибута задавать. Используйте это, чтобы пропустить обработку всей формы, ожидаемой для определенных полей (с немедленным). Например. Кнопка «Забыли пароль» в форме входа в систему с обязательным, но не немедленным паролем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...