【问题标题】:Adding inputText elements dynamically to a bound dataTable empties other inputTexts将 inputText 元素动态添加到绑定的 dataTable 会清空其他 inputText
【发布时间】:2012-09-23 08:09:03
【问题描述】:

我正在设计一个表单制作器,用户可以在其中为他们的问题添加多个选项。因此,每个选项都有一个添加新选项按钮和一个删除按钮。 我想在我的 Facelets 页面中使用 dataTable 并将其与托管 bean 中的 HtmlDataTable 绑定,以便动态添加/删除选项,因为我们不知道他们想要添加多少选项。 所以我所做的是我的dataTable 的值是字符串的List。我的输入文本(选项)被添加和删除,当他们添加整个问题时,它们被正确存储在我的数据库中。但是每次按下添加或删除按钮时,我的选项都是空的,因此用户必须再次输入它们。 我的代码有点长,所以我会为您提供它们的简化版本。

在我的 Facelets 页面上,我有:

<h:dataTable value="#{questionMaker.selectOneOptionList}" var="option" binding="#{questionMaker.table}"> 
<h:column>                                                                                     
<h:inputText value="#{option}"/>
<h:commandLink value="remove option" action="#{questionMaker.removeRadioButtonOption}"/>                                           
</h:commandLink>
</h:column>
</h:dataTable>

在我的托管 bean 中,上述变量是:

private HtmlDataTable table;
private List<String> selectOneOptionList;

当然,他们也有 getter 和 setter。 这是我的添加方法:

public void addRadioButtonOption() {
    String option = new String();
    selectOneOptionList.add(option);

}

【问题讨论】:

    标签: jsf facelets


    【解决方案1】:

    这种方法有几个(潜在的)问题:

    • 为了让这个构造工作,bean 必须是视图范围(不是请求或会话范围)。在请求范围内,selectOneOptionList 将在每个请求上重新创建。你不想拥有那个。在会话范围内,bean 将在所有浏览器窗口/选项卡之间共享。你也不想这样。

    • binding 属性在视图构建期间运行。因此,如果#{questionMaker} 是视图范围的,那么由于JSF issue 790,它会成为隐式请求范围。

    • 作为不可变对象,String 没有 setter 方法。 &lt;h:inputText value="#{option}"/&gt; 将永远无法设置输入的值。

    所以,要解决您的问题,您必须:

    • 确保您的 bean 是 @ViewScoped
    • 不要让binding 属性指向视图范围的bean 属性。
    • 要么将String 替换为完全有价值的javabean,要么按索引访问列表项。

    所以,应该这样做(假设您出于某种原因仍想坚持使用List&lt;String&gt;):

    <h:dataTable value="#{questionMaker.selectOneOptionList}" binding="#{table}"> 
      <h:column>                                                                                     
        <h:inputText value="#{questionMaker.selectOneOptionList[table.rowIndex]}"/>
        ...
      </h:column>
    </h:dataTable>
    <h:commandButton value="add" action="#{questionMaker.addRadioButtonOption}" />
    

    @ManagedBean
    @ViewScoped
    public class QuestionMaker {
    
        private List<String> selectOneOptionList;
    
        @PostConstruct
        public void init() {
            selectOneOptionList = new ArrayList<String>();
        }
    
        public void addRadioButtonOption() {
            selectOneOptionList.add(new String());
        }
    
        public List<String> getSelectOneOptionList() {
            return selectOneOptionList;
        }
    
    }
    

    另见:

    【讨论】:

    • 这听起来像是一个了不起的解决方案@Balus。我现在要测试一下。但是你能告诉我我的桌豆应该是什么样子吗?它是否必须扩展/实现某些东西?
    • 不,只是一个简单的@ManagedBean 类。我更新了 bean 示例以显示最少的必要代码。对于另一个示例,另请参阅“CRUD 框架”链接。
    • 所以我的表 bean 将查看带有项目列表的 CRUD 示例。什么是物品?
    • 这只是模型。在你的情况下,也许Question
    • 当页面在单个窗口/选项卡中打开时,会话范围肯定“有效”。但正如回答:“在会话范围内,bean 将在所有浏览器窗口/选项卡之间共享。您也不希望拥有它。”。因此,在多个窗口/选项卡中打开同一个页面并在它们之间切换时进行播放。结果不直观且令人困惑!因此,这只是目的的错误范围。另请参阅第一个“另请参阅”链接。
    猜你喜欢
    • 2012-05-20
    • 2020-10-01
    • 2020-03-27
    • 2014-11-02
    • 1970-01-01
    • 1970-01-01
    • 2012-05-26
    • 2012-12-11
    • 1970-01-01
    相关资源
    最近更新 更多