简体   繁体   English

立即操作后重置单选按钮(转换器和ui:repeat神秘地涉及)

[英]Radio button is reset after immediate action (converter and ui:repeat mysteriously involved)

I came across a scenario were a set of radio buttons gets reset to a none-selected state whenever the view returns from an immediate action, although the actual value is processed correctly. 我遇到了一个场景,尽管视图的正确值得到了正确处理,但只要视图从即时操作返回,就会将一组单选按钮重置为未选择状态。 Refreshing the view also displays the correct value. 刷新视图也会显示正确的值。 Weirdly enough, the behavior does only occur when the component uses an converter and is not inside a ui:repeat I narrowed it down to the following example: 古怪的是,当组件使用的转换器是不是里面也只发生行为ui:repeat我把范围缩小到了下面的例子:

JSF Page JSF页面

<ui:repeat value="#{bean.stringList}" var="item" varStatus="iteration">        
    #{item} 
    <h:selectOneRadio value="#{bean.boolValue}" rendered="#{iteration.last}">
        <f:selectItems value="#{bean.boolItemList}" />
        <f:converter converterId="testConverter" />      
    </h:selectOneRadio><br /><br />

</ui:repeat>
<hr /> 
<h:selectOneRadio value="#{bean.stringValue}">
    <f:selectItems value="#{bean.stringItemList}" />                 
</h:selectOneRadio>    

<h:selectOneRadio value="#{bean.boolValue}">
    <f:selectItems value="#{bean.boolItemList}" />
    <f:converter converterId="testConverter" />        
</h:selectOneRadio>

<p>
<h:commandButton value="Submit" type="submit" />
<h:commandButton value="Do nothing, but immediate!" immediate="true" action="#{bean.doNothing}" />
</p>

<p>boolValue is: #{bean.boolValue}</p>

Backing Bean 菜豆

@ManagedBean(name = "bean")
@SessionScoped
public class Bean {

private List<String> stringList;
private List<SelectItem> stringItemList;
private List<SelectItem> boolItemList;
private boolean boolValue;    
private String stringValue;    
private int removeParam;

public Bean() {
    stringList = new ArrayList<String>();
    stringList.add("Test Item One");      
    stringList.add("Test Item Two");  

    stringItemList = new ArrayList<SelectItem>();
    stringItemList.add(new SelectItem("1", "Option One"));
    stringItemList.add(new SelectItem("2", "Option Two"));      

    boolItemList = new ArrayList<SelectItem>();
    boolItemList.add(new SelectItem(Boolean.TRUE, "This is real"));
    boolItemList.add(new SelectItem(Boolean.FALSE, "This is not real"));                                                                    
    }
// + getters and setters

public void doNothing(){
    }
}

Converter 转换器

@FacesConverter("testConverter")
public class TestConverter implements Converter {

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value)
{       
    if (value!= null) {
        if (value.equals("real"))
        { 
        return Boolean.TRUE;          
        }
    }
    return Boolean.FALSE;
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
    boolean check = (Boolean) value;
    if (check)  return "real";
    else        return "unreal";
    }
}

So we have: 因此,我们有:

  • a group of radio buttons built from a backing bean list of SelectItem(String, String) , saved to a String. SelectItem(String, String)的后备bean列表构建的一组单选按钮,保存到String。 No converter needed. 无需转换器。
  • a group of radio buttons built from a backing bean list of SelectItem(boolean, String) , saved to a boolean. SelectItem(boolean, String)的后备bean列表构建的一组单选按钮,保存到布尔值。 A converter is provided to map the boolean to some words ("real"/"unreal") - just to replace the standard converter ("true"/"false") 提供了一个转换器来将布尔值映射到某些单词(“真实” /“虚幻”)-只是替换标准转换器(“ true” /“ false”)
  • A submit button + output to test if values get set correctly. 提交按钮+输出以测试值是否正确设置。
  • A button with some immediate action, which does nothing else but change the JSF lifecycle. 具有一些立即动作的按钮,除了更改JSF生命周期外,它什么也不做。

With this, one can play around and observe the following: 有了它,人们可以玩转并观察以下内容:

  • Whenever the page returns from the immediate action, the radios with converter outside ui:repeat display no value, meaning: no radio is selected 每当页面从立即操作返回时,带有ui:repeat 之外的转换器的无线电都不会显示任何值,这意味着:未选择任何无线电
  • However, the value is actually set correctly during submit. 但是,该值实际上是在提交过程中正确设置的。 Refreshing the page will results in correctly set radios. 刷新页面将导致无线电设置正确。
  • the same radio group inside ui:repeat works just fine, as does the one without the converter 相同的无线电组ui:repeat工作得很好,一样没有变流器的一个

Testing around against better knowledge I checked that the converter-radios put inside a <c:foreach> instead of ui:repeat show the same error (which is as I would have expected, as it merely builds the tree and then vanishes) and that attaching some standard converter to the string-radios does not make them break. 围绕更好的知识进行测试,我检查了放置在<c:foreach>而不是ui:repeat内的转换器无线电是否显示相同的错误(这是我所期望的,因为它只是构建树然后消失了),并且将一些标准转换器连接到字符串收音机不会使它们折断。 Regarding BalusC's comment, changing the bean to ViewScoped does not affect the problem - only then, refresh gives you a blank default-initialized page. 关于BalusC的注释,将Bean更改为ViewScoped不会影响该问题-只有这样,刷新才会为您提供空白的默认初始化页面。

Here I am at the end of my knowledge. 我的知识到此为止。 I don't really see how to reduce this any further or why it behaves like this. 我真的没有看到如何进一步减少它,或者为什么它表现得如此。 So... well... ideas anybody? 所以...好吧...有人有想法吗?

Specs I got from the server guy: Mojarra JSF API Implementation 2.0.5-FCS, JSF 2.0 and Facelets, Server is a Weblogic 11g 10.3 我从服务器人员那里得到的规格:Mojarra JSF API实施2.0.5-FCS,JSF 2.0和Facelets,服务器是Weblogic 11g 10.3

I still have no real understanding of why it behaves this way, but I found two solutions. 我对它为什么会这样仍然没有真正的了解,但是我找到了两种解决方案。

1) The doNothing() method does not comply with the spec , which demands that the signature must match java.lang.Object action() 1) doNothing()方法不符合spec ,它要求签名必须与java.lang.Object action()相匹配

If I correctly add a return value to go back to the same page (either through the file name "test.xhtml" or through outcome and navigation-rule in the faces-config), everything works fine. 如果我正确添加了返回值以返回同一页(通过文件名“ test.xhtml”或通过faces-config中的outcomenavigation-rule ),则一切正常。

2) If I add f:ajax to the button to execute and re-render part of the page everything is well. 2)如果我在按钮上添加f:ajax以执行并重新渲染页面的一部分,则一切正常。 I played around a bit and it does not seem to matter what part of the page is executed/re-rendered (other than the normal effects in applying values and such). 我玩了一会儿,似乎页面的哪一部分执行/重新渲染并不重要(除了应用值等的正常效果外)。

I am still a bit confused by the initially rather random behavior (and how ui:repeat and converters influence it). 我仍然对最初的随机行为(以及ui:repeat和转换器如何影响它)感到困惑。 It seems that my understanding of how JSF returns to a page without explicit navigation is incomplete. 似乎我对JSF如何在没有显式导航的情况下返回页面的理解是不完整的。 This also applies to getting back after failed validation via FacesContext#renderResponse . 这也适用于通过FacesContext#renderResponse验证失败后返回。 Any help appreciated (I could also open a new question if appropriate and then edit this answer) 任何帮助表示赞赏(如果合适,我也可以打开一个新问题,然后编辑此答案)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM