简体   繁体   English

Primefaces DataTable内联编辑-在不重新加载页面的情况下无法更新模型

[英]Primefaces DataTable inline editing - can't update model without reloading the page

I am trying to implement table with users' accounts, which can be modified by administrators. 我正在尝试使用用户帐户来实现表格,管理员可以对其进行修改。 I use primefaces (2.2) DataTable component with cellEditor. 我将primefaces(2.2)DataTable组件与cellEditor一起使用。

I have onRowEditListener which uses manageUsers.onEditRow() method to persist changes in database via UserDAO object. 我有onRowEditListener,它使用manageUsers.onEditRow()方法通过UserDAO对象将更改持久保存在数据库中。

After loading the page and updating table cell - data in database change properly. 加载页面并更新表格单元后-数据库中的数据正确更改。 Unfortunately, when I am trying to update previous row again - (UserDAO)event.getObject(); 不幸的是,当我尝试再次更新上一行时- (UserDAO)event.getObject(); returns old object (the one after first change) and data are not updated. 返回旧对象(第一次更改后的对象),并且数据不会更新。

When I reload page (F5) and edit row - then data are changed properly. 当我重新加载页面(F5)并编辑行时-则数据会正确更改。

How can I update table or how can I get the freshest version of user without reloading page? 如何更新表格或如何在不重新加载页面的情况下获得最新版本的用户?

Using Primefaces 2.2, JSF 2.1, Glassfish 3.1 使用Primefaces 2.2,JSF 2.1,Glassfish 3.1

PAGE: 页:

                <p:column headerText="login" filterBy="#{u.user.login}" filterMatchMode="contains" style="width:150px">  
                    <p:cellEditor>  
                        <f:facet name="output">  
                            <h:outputText value="#{u.user.login}" />
                        </f:facet>  
                        <f:facet name="input">  
                            <h:form>
                                <p:inputText value="#{u.user.login}" />  
                            </h:form>
                        </f:facet>  
                    </p:cellEditor>  
                </p:column>  

                <p:column headerText="email" filterBy="#{u.user.email}" filterMatchMode="contains" style="width:150px">  
                    <p:cellEditor>  
                        <f:facet name="output">  
                            <h:outputText value="#{u.user.email}" />  
                        </f:facet>  
                        <f:facet name="input">  
                            <h:form>
                                <p:inputText  value="#{u.user.email}" />  
                            </h:form>
                        </f:facet>  
                    </p:cellEditor>  
                </p:column> 

                //... other fields


                <p:column headerText="Options">  
                    <p:rowEditor />  
                </p:column>  

            </p:dataTable>  

        </h:form>

ManageBean with ApplicationScope (CDI) 带ApplicationScope(CDI)的ManageBean

@Named
@ApplicationScoped
public class ManageUsers implements Serializable {

    @Inject
    /** Inject database */
    private DB db;
    /** List with all leaked data which is loaded from database */
    private List<UserDAO> users;
    private User selectedUser;
    private SelectItem[] manufacturerOptions;

    public ManageUsers() {
        manufacturerOptions = createFilterOptions();
    }

    public SelectItem[] getManufacturerOptions() {
        return manufacturerOptions;
    }

    public User getSelectedUser() {
        return selectedUser;
    }

    public void setSelectedUser(User selectedUser) {
        this.selectedUser = selectedUser;
    }

    /** List of users loaded from database */
    public void getDataFromDatabase() {
        try {
            users = db.getUserList();
            if (users == null) {
                throw new Exception("Pusta lista użytkowników");
            }
        } catch (Exception ex) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Nie można wyświetlić tabeli wyników",
                    "Nie udało się pobrać danych, prosimy spróbować ponownie później.");
            FacesContext.getCurrentInstance().addMessage(null, message);
        }
    }

    /**
     * Get list of leaked Data.
     * If list is null then getDataFromDatabase method is used.
     * @see DataExplorer.getDataFromDatabase()
     */
    public List<UserDAO> getUsers() {
        if (users == null) {
            getDataFromDatabase();
        }
        return users;
    }

    private SelectItem[] createFilterOptions() {
        SelectItem[] options = new SelectItem[3];
        options[0] = new SelectItem("", "-select-");
        options[1] = new SelectItem("true", "Admins");
        options[2] = new SelectItem("false", "Users");

        return options;
    }

    public void onEditRow(RowEditEvent event){ 
        UserDAO userDAO = (UserDAO)event.getObject();
        try {
            userDAO.update();
        } catch (UserDAOException ex) {
            Log.logger.error("User not edited,"+ex);
        }
        //getDataFromDatabase();
    }
}

You are always returning a new list which is a well known bad practice in JSF, fetching data in getter. 您总是返回一个新列表,这是JSF中的一个众所周知的坏习惯,它在getter中获取数据。 Getters may be called several times during JSF lifecycle. 在JSF生命周期中,多次调用Getter。 Cache your user list in a variable and better to use view scope. 将用户列表缓存在变量中,以更好地使用视图范围。

Inline edit/update actually works but you are losing the updated model by returning a new list every time. 内联编辑/更新实际上有效,但是您每次都通过返回新列表来丢失更新的模型。

I don't know if I really understood your problem but you can easily update your table or even better update your form but implementing a commandButton with update attribute: 我不知道我是否真的了解您的问题,但是您可以轻松地更新表,甚至更好地更新表单,但可以使用带有update属性的commandButton来实现:

Let's say you have a form and it's id is myTableForm , then inside that form you have your dataTable component and a commandButton component. 假设您有一个表单,其ID为myTableForm ,然后在该表单内,您有dataTable组件和commandButton组件。 This button will look like this: 此按钮将如下所示:

<p:commandButton ajax='true' value='PersistData' update='myTableForm' action='if really needed' />

You can refer to an action method only if you need to. 仅在需要时才可以引用操作方法。 Otherwise this button will only update your entire form by implementing an ajax request. 否则,此按钮将仅通过实施ajax请求来更新您的整个表单。 Ajax is by default true, but I added that attribute there for explicitly. 默认情况下,Ajax是true,但是我在此处明确添加了该属性。

Of course you can have another logic design...you don't have to implement a button to do that, you could have some ajax listeners, some javascript functions that will be triggered at page load, edit cells etc... I have chosen a commandButton because it's the easiest way to understand the logic... 当然,您可以进行另一种逻辑设计...您不必实现按钮即可实现,您可以具有一些Ajax侦听器,一些将在页面加载,编辑单元格等情况下触发的javascript函数...我有选择了一个commandButton,因为它是理解逻辑的最简单方法。

Please let me know if this was really what you wanted. 请让我知道这是否真的是您想要的。

Problem solved. 问题解决了。 There are extra h:form around p:inputText =_= p:inputText = _ =周围有额外的h:form

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

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