简体   繁体   English

Bean对象在RowEdit上自行更新

[英]Bean Object Updating Itself on RowEdit

I'm creating a JSF 2.2 CRUD page, using primefaces datatable together with RowEditor. 我正在使用Primefaces数据表和RowEditor创建一个JSF 2.2 CRUD页面。

My problem lies in editing the Row. 我的问题在于编辑行。 I use 2 different listeners to compare the record before and after the edit (to make sure there are any modifications, etc) 我使用2个不同的监听器来比较编辑前后的记录(以确保有任何修改等)

To do so, I'm making use of RowEditInit to get the Initial value, as soon as the user clicks on the pencil icon. 为此,我会在用户单击铅笔图标后立即使用RowEditInit获取初始值。

After the user changes the row data, I use the RowEdit event to make some checks and compare the before and after values, but my initial object ends up getting the same values the user typed after clicking save. 用户更改行数据后,我使用RowEdit事件进行一些检查并比较之前和之后的值,但是我的初始对象最终得到的结果与用户单击保存后键入的值相同。

HTML CODE HTML代码

 <h:form id="edicao" prependId="false">
            <p:growl id="msgs" showDetail="true" globalOnly="true" escape="true"/>
            <p:dataTable id="dataTable" var="linha"  value="#{perfilMB.listaPerfilEntities}" 
                         editable="true" draggableColumns="true" rendered="#{not empty perfilMB.listaPerfilEntities}"
                         widgetVar="tablePerfil" filteredValue="#{perfilMB.filteredPerfilEntities}"
                         emptyMessage="Não existem registros." resizableColumns="true" styleClass="datatable_cadastro" >

                <f:facet name="header">
                    <span class="titulo_datatable" >Tabela Perfil</span>
                    <p:commandButton id="toggler" type="button" value="Colunas" />
                    <p:columnToggler datasource="dataTable" trigger="toggler" />
                </f:facet>

                <p:ajax event="rowEdit" listener="#{perfilMB.onRowEdit}" update=":edicao:msgs" />
                <p:ajax event="rowEditCancel" listener="#{perfilMB.onRowCancel}" update=":edicao:msgs" />
                <p:ajax event="rowEditInit" listener="#{perfilMB.rowEditInit}" />   

                <p:column headerText="ID" sortBy="#{linha.id}"
                    style="width:50px;">
                    <p:outputLabel value="#{linha.id}" style="width:100%" />
                </p:column>
                <p:column headerText="NOME" filterBy="#{linha.perfil}"
                    filterMatchMode="contains" sortBy="#{linha.perfil}"
                    style="width:100%;">
                    <p:cellEditor>
                        <f:facet name="output">
                            <h:outputText value="#{linha.perfil}" />
                        </f:facet>
                        <f:facet name="input">
                            <p:inputTextarea value="#{linha.perfil}" id="nome"
                                update=":edicao" style="width:100%" />
                        </f:facet>
                    </p:cellEditor>
                </p:column>
                <p:column headerText="DETALHAMENTO"
                    style="width:100%;"
                    sortBy="#{linha.descritivo}" filterBy="#{linha.descritivo}"
                    filterMatchMode="contains">
                    <p:cellEditor>
                        <f:facet name="output">
                            <h:outputText value="#{linha.descritivo}" />
                        </f:facet>
                        <f:facet name="input">
                            <p:inputTextarea value="#{linha.descritivo}"
                                id="detalhamento" update=":edicao" />
                        </f:facet>
                    </p:cellEditor>
                </p:column>

                <p:column headerText="ATIVO" style="width:150px;" filterBy="#{linha.ativo}" filterMatchMode="equals">
                        <f:facet name="filter">
                            <p:selectOneMenu onchange="PF('tablePerfil').filter()" >
                                <f:converter converterId="javax.faces.Character"/>
                                <f:selectItem itemLabel="TODOS" itemValue=""/>
                                <f:selectItem itemLabel="ATIVO" itemValue="T"/>
                                <f:selectItem itemLabel="INATIVO" itemValue="F"/>
                            </p:selectOneMenu>
                        </f:facet>
                        <p:cellEditor>
                            <f:facet name="output">
                                <p:selectBooleanCheckbox value="#{perfilMB.charToBool(linha.ativo)}" disabled="true"/> 
                            </f:facet>
                            <f:facet name="input">
                                <p:selectBooleanCheckbox value="#{perfilMB.ativo}" id="ativo" immediate="true" update=":edicao" style="width:100%"/>
                            </f:facet>

                        </p:cellEditor> 
                    </p:column>

                <p:column headerText="!" style="width:40px">
                    <p:rowEditor />
                </p:column>
                <p:column headerText="X" style="width:40px">
                    <p:commandLink styleClass="ui-icon ui-icon-trash" action="#{perfilMB.preparaParaDeletar(linha)}" update=":confirmacao_exclusao" oncomplete="PF('confirmacao').show()" />
                </p:column>

            </p:dataTable>  

        </h:form>

BEAN 豆角,扁豆

@ViewScoped @ViewScoped

Imports 进口货

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

import org.primefaces.event.RowEditEvent;

Workflow: 工作流程:

1 - User Clicks the Edit Row Button, triggering RowEditInit. 1-用户单击“编辑行”按钮,触发RowEditInit。

2 - The Object perfilAntes gets the initial value from that row. 2-对象perfilAntes从该行获取初始值。

RowEditInit Method RowEditInit方法

public void rowEditInit(RowEditEvent event) {
    Object value = event.getObject();
    perfilAntes = new PerfilEntity();
    perfilAntes = (PerfilEntity) value;
}

3 - After the user finishes editing the data, he clicks on save, that calls the RowEdit Method. 3-用户完成数据编辑后,单击“保存”,即调用RowEdit方法。

4 - A new object names perfilTela gets the new value user has typed. 4-新对象名称perfilTela获取用户键入的新值。

5 - Call the validaOnRowEdit method that compare the two objects against each other. 5-调用validaOnRowEdit方法,将两个对象相互比较。

RowEdit Method RowEdit方法

public void onRowEdit(RowEditEvent event) {

    context = FacesContext.getCurrentInstance();

    Object value = event.getObject();

    PerfilEntity perfilTela = (PerfilEntity) value;

    if(perfilTela.getId() != null){

        /* Calls the validation method  */
        boolean validado = validaOnRowEdit(perfilTela);

         /* if its all Good, saves the data on database*/
        if(validado){
        /*removed code*/
        }           
}

DataValidation Method 数据验证方法

This method is comparing the two objects, PerfilAntes (The initial value) with the PerfilTela (The value the user typed). 此方法将两个对象PerfilAntes(初始值)与PerfilTela(用户键入的值)进行比较。

When I inspect the object values, the PerfilAntes Object loses its initial value and it's equal to PerfilTela Object! 当我检查对象值时,PerfilAntes对象会丢失其初始值,它等于PerfilTela对象!

public boolean validaOnRowEdit(PerfilEntity perfilTela){
        if(perfilAntes.getId() != null){
            if( perfilTela.getPerfil().trim() != null && perfilTela.getDescritivo().trim() != null ){
                if( perfilTela.getPerfil().equals(perfilAntes.getPerfil() ) 
                    && perfilTela.getDescritivo().equals(perfilAntes.getDescritivo() ) 
                    && perfilTela.getAtivo() == perfilAntes.getAtivo() ){

                    perfilTela = perfilAntes;
                    context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Changes Canceled" ,"There was no changes in row <br/><b>Case Insensitive<b/>" ));
                    return false;
                } else {
                    return true;
                }
            } else {
                perfilTela = perfilAntes;
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Changes canceled" ,"No field can be empty or contain spaces" ));
                return false;
            }
        }
    }

尝试使用@SessionScoped bean,看看会发生什么,您的代码似乎还不错。

I found out what the problem was. 我发现了问题所在。

When using Object variables, and you create objects and set values like this: 使用对象变量时,您可以创建对象并设置如下值:

Object object1 = new Object();
Object object2 = new Object();
object1 = object2;

The objects variables don't save the object values inside these variables, instead they save only the reference between the variable in the Stack and Heap memories. 对象变量不会将对象值保存在这些变量中,而是仅保存堆栈内存中的变量之间的引用。

So when I set: object1 = object2; 所以当我设置时:object1 = object2;

The object1 is receiving a "pointer" to the object set on object2, and if I edit one of the attributes using either one of these variables, both will be changed because it contains only a link. object1正在接收指向object2上设置的对象的“指针”,并且如果我使用这些变量之一编辑属性之一,则两个属性都将被更改,因为它仅包含一个链接。

And because I set object1 = object2, the previously linked object on object1 that exists on the Heap can't be used anymore and will be cleaned by the Garbage Collector. 而且因为我设置object1 = Object2的,在object1,关于存在以前链接的对象不能再被使用,并且将被垃圾收集器进行清洗。

So I ended up setting the values using setters. 因此,我最终使用设置器设置了值。

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

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