У меня есть страница 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