我的行为是我不理解的选择菜单。我会试着解释一下,想知道是否有人知道发生了什么。我正在使用JSF2和glassfish3。 我的xhtml代码如下:
<h:selectOneMenu binding="#{cetBacking1.menuFamilies}"
valueChangeListener="#{cetBacking1.listenerFamilia}"
onchange="this.form.submit()">
<f:selectItems value="#{cetBacking1.ompleFamiliesTemplate()}"></f:selectItems>
</h:selectOneMenu>
<h:commandButton value="Test" type="submit" action="#{cetBacking1.test()}"> </h:commandButton>
我使用绑定,因为取决于selectOneMenu值,我将呈现一些其他组件,但现在这超出了范围。命令按钮用于提交。 ompleFamiliesTemplate()返回一个选择项列表。 支持bean是:
@ManagedBean(name="cetBacking1")
@SessionScoped
public class cetBacking1 extends AbstractEntityAccessor implements Serializable {
private List<SelectItem> llistaFamilies = new ArrayList<SelectItem>();
private HtmlSelectOneMenu menuFamilies;
{
System.out.println("cetBacking1.init");
ompleFamiliesTemplate();
}
public void listenerFamilia(ValueChangeEvent event) {
String novaFamilia = (String) event.getNewValue();
System.out.println("cetBacking1.listenerFamilia: " + novaFamilia);
}
public List ompleFamiliesTemplate() {
FacesContext context = FacesContext.getCurrentInstance();
List<FamiliaTemplate> llistaFamiliestmp = new ArrayList<FamiliaTemplate>();
System.out.println("cetBacking1.ompleFamiliesTemplate !!!!!!");
if (context.getExternalContext().getSessionMap().containsKey("LlistaFamilies")) {
llistaFamiliestmp = (List<FamiliaTemplate>) context.getExternalContext().getSessionMap().get("LlistaFamilies");
if (llistaFamilies.isEmpty()) {
for (Iterator it = llistaFamiliestmp.iterator(); it.hasNext();) {
FamiliaTemplate object = (FamiliaTemplate) it.next();
llistaFamilies.add(new SelectItem(String.valueOf(object.getIdfamiliaTemplate()), object.getFamilia()));
}
}
}
return llistaFamilies;
}
public void submit() {
System.out.println("cetBacking1.submit !!");
}
我放了一些System.out.println来跟随对不同函数的调用,cetBacking1 bean构造函数和ompleFamiliesTemplate()以及valueChangeListener。 第一次在服务器日志中加载页面时,将显示下一条消息:
INFO: cetBacking1.init
INFO: cetBacking1.ompleFamiliesTemplate !!!!!!
INFO: cetBacking1.ompleFamiliesTemplate !!!!!!
调用bean的{}函数,它调用cetBacking1.ompleFamiliesTemplate,第二个cetBacking1.ompleFamiliesTemplate由f:selectItems调用。它按预期工作。现在我更改了selectOneMenu的值,并在日志中显示:
INFO: cetBacking1.ompleFamiliesTemplate !!!!!!
INFO: cetBacking1.ompleFamiliesTemplate !!!!!!
INFO: cetBacking1.listenerFamilia: 2
INFO: cetBacking1.listenerFamilia: 2
INFO: cetBacking1.ompleFamiliesTemplate !!!!!!
最后一次调用cetBacking1.ompleFamiliesTemplate我认为这是由f:selectItems调用的。但是我不知道为什么在开始时两次调用cetBacking1.ompleFamiliesTemplate然后两次调用cetBacking1.listenerFamilia。 但接下来对我来说更令人惊讶。我再次更改selectOneMenu并在日志中显示: 信息:cetBacking1.ompleFamiliesTemplate !!!!!! 信息:cetBacking1.ompleFamiliesTemplate !!!!!! 信息:cetBacking1.listenerFamilia:3 信息:cetBacking1.listenerFamilia:3 信息:cetBacking1.listenerFamilia:3 信息:cetBacking1.ompleFamiliesTemplate !!!!!!
cetBacking1.ompleFamiliesTemplate在开始时被调用两次,但是监听器被调用三次。每次我更改selectOneMenu时,都会再次调用侦听器。如果我将selectOneMenu值更改两次,则日志如下:
INFO: cetBacking1.ompleFamiliesTemplate !!!!!!
INFO: cetBacking1.ompleFamiliesTemplate !!!!!!
INFO: cetBacking1.listenerFamilia: 1
INFO: cetBacking1.listenerFamilia: 1
INFO: cetBacking1.listenerFamilia: 1
INFO: cetBacking1.listenerFamilia: 1
INFO: cetBacking1.ompleFamiliesTemplate !!!!!!
INFO: cetBacking1.ompleFamiliesTemplate !!!!!!
INFO: cetBacking1.ompleFamiliesTemplate !!!!!!
INFO: cetBacking1.listenerFamilia: 2
INFO: cetBacking1.listenerFamilia: 2
INFO: cetBacking1.listenerFamilia: 2
INFO: cetBacking1.listenerFamilia: 2
INFO: cetBacking1.listenerFamilia: 2
INFO: cetBacking1.ompleFamiliesTemplate !!!!!!
问题是为什么在监听器执行之前更改selectOneMenu值时会调用cetBacking1.ompleFamiliesTemplate两次。为什么第一次更改selectOneMenu值时,侦听器执行两次,然后每次更改值时再执行一次。
提前致谢
答案 0 :(得分:1)
在JSF中,可以在单个请求中多次调用getter。这是一个很好的答案:Why JSF calls getters multiple times
答案 1 :(得分:0)
一个月前,我遇到了同样的问题。 解决方案是,SessionScope和绑定不兼容。
您必须删除jsf页面中的绑定,一切正常。
要填充SelectCombo,您可以将List<SelectItem>
与项目一起使用。