Изменения в объекте поддержки в actionListener, не отраженные в связанных элементах пользовательского интерфейса - PullRequest
0 голосов
/ 25 июля 2011

У меня есть страница JSF с переменным числом элементов inputText, содержащих числовые веса.Все они связаны с объектами веса в моем бобе.Я хотел бы создать одну кнопку actionListener, которая будет перераспределять веса по всем входным текстам.

Я могу вызвать метод в компоненте поддержки, который распределяет значения, содержащиеся в объектах весов в компоненте поддержки, но по некоторым причинам эти обновленные значения не отражаются в элементах InputText.

Я предполагаю, что значения возвращаются в элементы пользовательского интерфейса, прежде чем я обновлю значения.Просто показывает мое непонимание жизненного цикла JSF.

Может кто-нибудь сказать мне, как я мог бы сделать это?

Вот соответствующая часть файла xhtml.Для каждого дочернего объекта я ссылаюсь на ключ объекта "newWeight" дочернего объекта.Объекты newWeight создаются в методе loadFamily, который связан с событием preRenderView:

<!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">

<ui:composition template="/templates/layout.xhtml">
<f:metadata>
    <f:viewParam name="familyId" required="true"
        requiredMessage="familyId is required"
        value="#{weighFamilyBacking.familyId}"></f:viewParam>
    <f:event type="preRenderView"
        listener="#{weighFamilyBacking.loadFamily}" />
</f:metadata>
<ui:define name="title">Weigh Family</ui:define>
<ui:define name="content">
    <h:form>
        <h2>Previous Weights</h2>

        <rich:dataTable value="#{weighFamilyBacking.allWeights}" var="weight"
            id="table">
            <rich:column>
                <f:facet name="header">
                    <h:outputText value="Child" />
                </f:facet>
                <h:outputText
                    value="#{weight.child.firstName} #{weight.child.lastName}" />
            </rich:column>

            <rich:column>
                <f:facet name="header">
                    <h:outputText value="Weight" />
                </f:facet>
                <h:outputText value="#{weight.weight}" />
            </rich:column>


            <rich:column>
                <f:facet name="header">
                    <h:outputText value="Weigh Time" />
                </f:facet>
                <h:outputText value="#{weight.weighTime}" />
            </rich:column>

            <rich:column>
                <f:facet name="header">
                    <h:outputText value="Payout Time" />
                </f:facet>
                <h:outputText value="#{weight.payoutTime}" />
            </rich:column>
            <rich:column>
                <f:facet name="header">
                    <h:outputText value="Payout Status" />
                </f:facet>
                <h:outputText value="#{weight.status}" />
            </rich:column>
        </rich:dataTable>

        <h2>New Weights</h2>


        <h:panelGroup id="newWeights">
            <ul>
                <ui:repeat var="child" value="#{weighFamilyBacking.children}">
                    <li><h:panelGroup layout="block">
                            <h:outputText value="#{child.firstName}" />
                            <h:outputLabel value="Lbs" for="lbs">
                                <h:inputText size="3" id="lbs"
                                    value="#{weighFamilyBacking.newWeights[child].lbs}" />
                            </h:outputLabel>

                            <h:outputLabel value="Oz" for="oz">
                                <h:inputText id="oz" size="3"
                                    value="#{weighFamilyBacking.newWeights[child].oz}" />
                            </h:outputLabel>
                        </h:panelGroup></li>
                </ui:repeat>
                <h:outputLabel value="Donate Only" for="donate">
                    <h:selectBooleanCheckbox id="donate"
                        value="#{weighFamilyBacking.donateOnly}" />
                </h:outputLabel>
            </ul>
        </h:panelGroup>
        <h:commandButton
            actionListener="#{weighFamilyBacking.distributeWeights}"
            immediate="true" value="Redistribute" />
        <h:commandButton action="cancel" value="Cancel" />
        <h:commandButton action="#{weighFamilyBacking.save}" value="Save" />
    </h:form>

</ui:define>
</ui:composition>
</html>

Вот базовый компонент:

@ViewScoped
@ManagedBean
public class WeighFamilyBacking extends BaseForm implements Serializable {

private static final long serialVersionUID = 3710213437377609887L;
private Integer familyId;
private Boolean donateOnly;

public Boolean getDonateOnly() {
    return donateOnly;
}

public void distributeWeights(ActionEvent event) {
    Integer oz = 0;
    Integer count = 0;

    for (WebWeight ww : newWeights.values()) {
        System.out.println(ww);
        oz += ww.getLbs() * 16;
        oz += ww.getOz();
        ww.setLbs(123); // Set the values to something to simulate re-distribution for now.
        ww.setOz(456);
        count++;
    }

    donateOnly = true;

}

public void setDonateOnly(Boolean donateOnly) {
    this.donateOnly = donateOnly;
}

private Family family;
private HashMap<Child, WebWeight> newWeights;

public HashMap<Child, WebWeight> getNewWeights() {
    return newWeights;
}

public void setNewWeights(HashMap<Child, WebWeight> newWeights) {
    this.newWeights = newWeights;
}

public WeighFamilyBacking() {
    newWeights = new HashMap<Child, WebWeight>();
}

public List<Weight> getAllWeights() {
    List<Weight> weights = new ArrayList<Weight>();
    for (Child c : getFamily().getChildrenAsList()) {
        for (Weight w : c.getWeightsAsList())
            weights.add(w);
    }

    Collections.sort(weights, new Comparator<Weight>() {

        @Override
        public int compare(Weight arg0, Weight arg1) {
            if (arg0.getWeighTime() == null)
                return -1;

            Integer date = arg0.getWeighTime().compareTo(
                    arg1.getWeighTime());

            if (date == 0)
                return arg0.getChild().getFirstName()
                        .compareTo(arg1.getChild().getFirstName());

            return date;
        }
    });

    return weights;
}

@PostConstruct
public void init() {

}

public void loadFamily() {
    if (family == null) {
        setFamily(hcbbService.findFamilyById(getFamilyId()));

        for (Child c : family.getChildrenAsList()) {
            WebWeight w = new WebWeight();
            newWeights.put(c, w);
        }
    }
}

public void setFamilyId(Integer id) {
    this.familyId = id;
}

public Integer getFamilyId() {
    return this.familyId;
}

public Family getFamily() {
    return family;
}

public void setFamily(Family f) {
    this.family = f;
}

public List<Child> getChildren() {
    List<Child> children = getFamily().getChildrenAsList();
    Collections.sort(children);
    return children;
}

public String cancel() {
    return "cancel";
}

public String save() {
    for (Child c : newWeights.keySet()) {
        WebWeight ww = newWeights.get(c);
        Weight w = new Weight();
        w.setWeighTime(new Date());
        Double weight = (ww.getLbs() * 16.0 + ww.getOz()) / 16.0;
        w.setWeight(weight);
        w.setStatus(WeightStatus.AWAITING_PAYOUT);
        c.getWeights().add(w);
    }

    hcbbService.updateRegistration(family);

    return "success";
}
}

Цель состоит в том, чтобы позволить нам выставлять весав одном дочернем элементе, а затем равномерно распределить значения по всем объектам "newWeight".Прямо сейчас я ожидаю, что все мои элементы пользовательского интерфейса, связанные с объектами NewWeight, будут нулевыми после того, как я нажму на перераспределение (так как этот метод вызывается, а значения сбрасываются), но это не так.

Дополнительная информация

Моя настройка объектов WebWeight происходит на этапе INVOKE_APPLICATION, как и ожидалось.Объекты имеют правильные значения до ответа Render .. но не в визуализированных компонентах?

Из журнала:

BEFORE INVOKE_APPLICATION 5
net.halo3.hcbb.registration.WebWeight@2f6cd09f
net.halo3.hcbb.registration.WebWeight@10f48f0c
net.halo3.hcbb.registration.WebWeight@27db6586 
AFTER INVOKE_APPLICATION 5
BEFORE RENDER_RESPONSE 6
oz=456 lbs=123 object=net.halo3.hcbb.registration.WebWeight@2f6cd09f
oz=456 lbs=123 object=net.halo3.hcbb.registration.WebWeight@10f48f0c
oz=456 lbs=123 object=net.halo3.hcbb.registration.WebWeight@27db6586
AFTER RENDER_RESPONSE 6

Подробнее

Вот дамп из журналов, где я регистрирую getLbs и getOz .. Вы можете увидетьчто getLbs или getOz для объекта WebWeight не вызывается на этапе рендеринга?

 - BEFORE INVOKE_APPLICATION 5
net.halo3.hcbb.registration.WebWeight@12d58dfe
net.halo3.hcbb.registration.WebWeight@12d58dfe getLbz: 0
net.halo3.hcbb.registration.WebWeight@12d58dfe getOz:0
net.halo3.hcbb.registration.WebWeight@25d285b
net.halo3.hcbb.registration.WebWeight@25d285b getLbz: 0
net.halo3.hcbb.registration.WebWeight@25d285b getOz:0
net.halo3.hcbb.registration.WebWeight@6c317dc9
net.halo3.hcbb.registration.WebWeight@6c317dc9 getLbz: 0
net.halo3.hcbb.registration.WebWeight@6c317dc9 getOz:0 
- AFTER INVOKE_APPLICATION 5
- BEFORE RENDER_RESPONSE 6
- AFTER RENDER_RESPONSE 6

Ответы [ 2 ]

1 голос
/ 26 июля 2011

Дело в том, что вы установили непосредственный атрибут на командную кнопку.

Это приведет к тому, что ваш слушатель действия будет вызываться во время фазы APPLY_REQUEST, но дополнительно UPDATE_MODEL не будет вызываться, и при повторном представлении представление будет отображать значения, которые все еще были во входных компонентах (компоненты с состояниемв JSF).

См. более подробную информацию: JSF commandButton с немедленным = "true"

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

(оффтоп, но я заметил, что ваш компонент поддержки имеет произвольную последовательность, что делает его немного трудным для чтения. В Java /JSF обычно вы помещаете переменные экземпляра в самом начале, затем в конструктор, метод post-конструкции, обработчик события preRenderView и т. Д., Чтобы класс читался как история сверху вниз)

0 голосов
/ 30 июля 2011

Оказалось, что проблема была в некоторых xhtml. Когда я все вычистил и начал просто, он начал работать. Я думаю, может быть, выходные этикетки или группы панелей.

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