8 Replies Latest reply on Jan 12, 2010 2:32 PM by csimons

    Editable dataTable with modalPanel problem

    daxxy

      I've asked this question a couple of times and gotten no response. I've pinned down the problem a little better. Hopefully someone can explain how this works.

      I based my app on this richfaces demo:

      http://livedemo.exadel.com/richfaces-demo/richfaces/dataTable.jsf?tab=editDataTable

      Here is how it seems the richfaces demo works. I've stepped through this on my local machine with the debugger:

      You click the edit icon in the Action column, and the object in the current row is loaded into dataScrollerBean.currentItem via f:setPropertyActionListener. Just for an example, let's say the debugger identifies this object with id 14866. The information in currentItem is made available for editing in the modalPanel.

      Clicking the Store button in the modalPanel, calls dataScrollerBean.store(). currentItem (id=14866) is available to the store() method allowing the recently edited input fields to be saved to the original object.

      Here is how mine works.

      You click the edit icon in the Action column, and the object in the current row is loaded into assetTagBean.currentItem (id=14932) via f:setPropertyActionListener. The information in currentItem is made available for editing in the modalPanel.

      Clicking the Store button in the modalPanel, calls assetTagBean.store(). The currentItem object is available to store(), but it is a newly instantiated currentItem (id=15821) that was created when the values on the input fields were bound to attributes of currentItem. The only fields populated in currentItem at this point are the input fields in the modalPanel. Therefore the original item cannot be updated.

      What is going on in the richfaces demo that I cannot reproduce?


      <ui:composition xmlns="http://www.w3.org/1999/xhtml"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:f="http://java.sun.com/jsf/core"
       xmlns:a4j="http://richfaces.org/a4j"
       xmlns:rich="http://richfaces.org/rich">
       <style>
      .active-row {
       background-color: #FFEBDA;
      }
      </style>
       <h:form>
       <script type="text/javascript">
       var row;
       </script>
       <a4j:region>
       <rich:dataTable value="#{devTagsList.resultList}"
       var="category" rows="20" rowKeyVar="row"
       ajaxKeys="#{assetTag.keys}" id="table"
       >
       <f:facet name="header">
       <h:outputText value="Asset Tags" />
       </f:facet>
       <rich:column>
       <f:facet name="header">
       <h:outputText value="Row Id" />
       </f:facet>
       <h:outputText value="#{row}" />
       </rich:column>
       <rich:column>
       <f:facet name="header">
       <h:outputText value="Tag" />
       </f:facet>
       <h:outputText value="#{category.devTagId}" id="model" />
       </rich:column>
       <rich:column>
       <f:facet name="header">
       <h:outputText value="Serial Number" />
       </f:facet>
       <h:outputText value="#{category.devSerialNum}" id="price" />
       </rich:column>
       <rich:column>
       <f:facet name="header">
       <h:outputText value="Comment" />
       </f:facet>
       <h:outputText value="#{category.comment}" />
       </rich:column>
       <rich:column width="200px">
       <f:facet name="header">
       <h:outputText value="Tag ID" />
       </f:facet>
       <h:outputText value="#{category.tagId}" />
       </rich:column>
       <rich:column>
       <f:facet name="header">
       <h:outputText value="Dev ID" />
       </f:facet>
       <h:outputText value="#{category.devId}" />
       </rich:column>
       <rich:column>
       <f:facet name="header">
       Actions
       </f:facet>
       <a4j:commandLink ajaxSingle="true" id="editlink"
       oncomplete="#{rich:component('editPanel')}.show()">
       <h:graphicImage value="/images/icons/edit.gif" style="border:0" />
       <f:setPropertyActionListener value="#{category}"
       target="#{assetTag.currentItem}" />
       <f:setPropertyActionListener value="#{row}"
       target="#{assetTag.currentRow}" />
       </a4j:commandLink>
       <rich:toolTip for="editlink" value="Edit" />
       <a4j:commandLink ajaxSingle="true" id="deletelink"
       oncomplete="#{rich:component('deletePanel')}.show()">
       <h:graphicImage value="/images/icons/delete.gif" style="border:0" />
       <f:setPropertyActionListener value="#{row}"
       target="#{assetTag.currentRow}" />
       </a4j:commandLink>
       <rich:toolTip for="deletelink" value="Delete" />
       </rich:column>
       </rich:dataTable>
       </a4j:region>
       </h:form>
      
       <rich:modalPanel id="editPanel" autosized="true" width="450">
       <f:facet name="header">
       <h:outputText value="Edit Current Asset Tag" />
       </f:facet>
       <f:facet name="controls">
       <h:panelGroup>
       <h:graphicImage value="/images/modal/close.png" id="hidelink"
       styleClass="hidelink" />
       <rich:componentControl for="editPanel" attachTo="hidelink"
       operation="hide" event="onclick" />
       </h:panelGroup>
       </f:facet>
       <h:form>
       <rich:messages style="color:red;"></rich:messages>
       <h:panelGrid columns="1">
       <a4j:outputPanel ajaxRendered="true">
       <h:panelGrid columns="2">
       <h:outputText value="Make" />
       <h:inputText value="#{assetTag.currentItem.devSerialNum}" />
       <h:outputText value="Model" />
       <h:inputText value="#{assetTag.currentItem.devTagId}" />
       <h:outputText value="Price" />
       <h:inputText value="#{assetTag.currentItem.comment}" />
       </h:panelGrid>
      
       </a4j:outputPanel>
       <a4j:commandButton value="Store"
       action="#{assetTag.store}"
       reRender="make, model, price"
       oncomplete="if (#{facesContext.maximumSeverity==null}) #{rich:component('editPanel')}.hide();" />
       </h:panelGrid>
       </h:form>
       </rich:modalPanel>
       <rich:modalPanel id="deletePanel" autosized="true" width="200">
       <f:facet name="header">
       <h:outputText value="Delete this car from list?"
       style="padding-right:15px;" />
       </f:facet>
       <f:facet name="controls">
       <h:panelGroup>
       <h:graphicImage value="/images/modal/close.png"
       styleClass="hidelink" id="hidelink2" />
       <rich:componentControl for="deletePanel" attachTo="hidelink2"
       operation="hide" event="onclick" />
       </h:panelGroup>
       </f:facet>
       <h:form>
       <table width="100%">
       <tbody>
       <tr>
       <td align="center" width="50%"><a4j:commandButton value="Yes"
       ajaxSingle="true" action="#{assetTag.delete}"
       oncomplete="#{rich:component('deletePanel')}.hide();"
       reRender="table" /></td>
       <td align="center" width="50%"><a4j:commandButton
       value="Cancel"
       onclick="#{rich:component('deletePanel')}.hide();return false;" />
       </td>
       </tr>
       </tbody>
       </table>
       </h:form>
       </rich:modalPanel>
       <a4j:status onstart="#{rich:component('wait')}.show()"
       onstop="#{rich:component('wait')}.hide()" />
       <rich:modalPanel id="wait" autosized="true" width="200" height="120"
       moveable="false" resizeable="false">
       <f:facet name="header">
       <h:outputText value="Processing" />
       </f:facet>
       <h:outputText value="Wait Please..." />
       </rich:modalPanel>
       <rich:messages></rich:messages>
      </ui:composition>
      
      



      /**
       *
       */
      package dne.nib.assettags.action;
      
      import java.util.HashSet;
      import java.util.Set;
      
      import org.jboss.seam.annotations.Name;
      
      import dne.nib.assettags.model.DevTags;
      
      
      @Name("assetTag")
      public class AssetTagBean {
      
       private DevTags currentItem = new DevTags();
      
      
       private Set<Integer> keys = new HashSet<Integer>();
      
       private int currentRow;
      
      
      
       public DevTags getCurrentItem() {
       return currentItem;
       }
      
       public void setCurrentItem(DevTags currentItem) {
       this.currentItem = currentItem;
       }
      
       public int getCurrentRow() {
       return currentRow;
       }
      
       public void setCurrentRow(int currentRow) {
       this.currentRow = currentRow;
       }
      
       public void store() {
       System.out.println("currentRow is"+ currentRow);
       System.out.println("currentItem is "+currentItem);
       }
      
       public Set<Integer> getKeys() {
       return keys;
       }
      
       public void setKeys(Set<Integer> keys) {
       this.keys = keys;
       }
      
      
      }
      


        • 1. Re: Editable dataTable with modalPanel problem
          csimons
          I am more or less having the same issue; did you ever find a fix?
          • 2. Re: Editable dataTable with modalPanel problem
            daxxy

            Yes, thankfully I have a redhat subscription and they helped me on this.

             

            I ended up populating the modalPanel (or instantiating a new object for the modalPanel) by explicitly calling an action from my commandLink.  Like this:

             

             

             

                        <a4j:commandLink ajaxSingle="true" id="editLink" reRender="editPanel"
                          action="#{AssetTagsHome.setTagId(_devices.assetTag.assetTagId)}"
                          oncomplete="#{rich:component('editPanel')}.show()"
                          rendered="#{not empty _devices.assetTag}">
                          <h:graphicImage value="/img/icons/edit.gif"
                            style="border:0" />
                        </a4j:commandLink>
                        <a4j:commandLink ajaxSingle="true" id="newLink" reRender="editPanel"
                          action="#{AssetTagsHome.createAssetTag(_devices.devId, _devices.devSerialNum)}"
                          oncomplete="#{rich:component('editPanel')}.show()"
                          rendered="#{empty _devices.assetTag}">
                          <h:graphicImage value="/img/icons/edit.gif"
                            style="border:0" />
                        </a4j:commandLink>

             

            And here is the modalPanel itself:

             

                <rich:modalPanel id="editPanel" autosized="true" width="450">
                  <f:facet name="header">Asset Tag</f:facet>
                  <f:facet name="controls">
                    <h:panelGroup>
                      <h:graphicImage value="/img/modal/close.png"
                        id="hideEditPanel" styleClass="hidelink"
                        onclick="#{rich:component('editPanel')}.hide()" />
                    </h:panelGroup>
                  </f:facet>
                  <h:form>
                    <rich:messages for="assetTagPanel" style="color:red;"></rich:messages>
                    <a4j:outputPanel ajaxRendered="true" id="assetTagPanel">
                      <h:panelGrid columns="2">
                        <h:outputText
                          value="Serial Number (change only if necessary): " />
                        <h:inputText value="#{AssetTagsHome.instance.devSerialNum}" />
                        <h:outputText value="Asset Tag" />
                        <h:inputText value="#{AssetTagsHome.instance.assetTag}"
                          required="true" />
                      </h:panelGrid>

             

                      <a4j:commandButton id="save" value="Save"
                        rendered="#{not AssetTagsHome.managed}"
                        action="#{officeViewHome.refreshInstance()}"
                        actionListener="#{AssetTagsHome.persist}" reRender="a4jp"
                        oncomplete="#{rich:component('editPanel')}.hide()" />
                      <a4j:commandButton id="update" value="Update"
                        rendered="#{AssetTagsHome.managed}"
                        action="#{AssetTagsHome.update}" reRender="a4jp"
                        oncomplete="#{rich:component('editPanel')}.hide()" />
                      <a4j:commandButton id="delete" value="Delete"
                        rendered="#{AssetTagsHome.managed}"
                        action="#{officeViewHome.refreshInstance()}"
                        actionListener="#{AssetTagsHome.remove}" immediate="true"
                        reRender="a4jp"
                        oncomplete="#{rich:component('editPanel')}.hide()" />
                    </a4j:outputPanel>
                  </h:form>
                </rich:modalPanel>

             

            Note there are 2 of these, one for loading an existing asset tag and one for creating a new one.  Here is the code behind it:

             

             

            @Scope(ScopeType.CONVERSATION)
            @Name("AssetTagsHome")
            public class AssetTagsHome extends EntityHome<AssetTags> {

             

                Integer assetTagId;

             

               
                @Begin(join = true)
                public void setTagId(Integer id) {

             

                    //setId(id);
                    this.assetTagId = id;
                    this.instance = this.getEntityManager().find(AssetTags.class,
                            this.assetTagId);
                }

             

                @Begin(join = true)
                public void createAssetTag(Integer devId, String devSerialNum) {
                    AssetTags newAssetTag = new AssetTags(devId, devSerialNum);
                    this.instance = newAssetTag;
                }

             

            }

             

            Hope this helps.  No way to preview it so I hope the lack of formatting doesn't make this too unreadable.

            • 3. Re: Editable dataTable with modalPanel problem
              csimons

              Thanks very much; I posted a few minutes ago about a nearly identicaly solution.  I had been using an action command (without the f:setPropertyActionListener), but when I found the example I figured I would go with what the RF gurus suggested.

               

              With what you provided, I believe I would have had it working simply by ignoring the ActionListener and just wrapping the modalPanel form with an a4j:outputPanel.

               

               

              Thank you.

              • 4. Re: Editable dataTable with modalPanel problem
                csimons
                Seems to still not be working for me; the only different is that I am not using an EntityHome in this situation.  I'm stumped.  I can't explain it one bit!
                • 5. Re: Editable dataTable with modalPanel problem
                  daxxy

                  What scope are you using?

                   

                  I only vaguely understand the different scopes, but if your entity is here today, gone tomorrow, it must have not been in the proper scope.  And when you went out of that scope, the entity disappeared.

                   

                  I explicitly specified a conversation scope and began the conversation when the modalPanel opened and one of the two methods were called.

                  • 6. Re: Editable dataTable with modalPanel problem
                    csimons

                    Thanks for the reply; I have tried everything I can think of.

                     

                    The problem seems to be that the modal panel is rendering before resetting the input controls from the backing bean.

                     

                    Case in point, on action, the correct value is being stored on the backing bean (validated through debugging).

                     

                    The modal panel opens, but is showing a form populated with information from the last entity to be clicked (not the current entity).

                     

                    This process continues ad nauseam; the modal panel form is always one step behind, even though the backing bean values are right.  If I modify the form and update the entity, the right entity is merged (even though the form didn't tell me so).

                     

                    Just to be sure, I modified my modal panel to access a conversational object and made sure to start a new conversation on the action.  Still not working.  I'm ready to give up.

                    • 7. Re: Editable dataTable with modalPanel problem
                      daxxy

                      why don't you post your code. maybe something will jump out that you missed.

                      • 8. Re: Editable dataTable with modalPanel problem
                        csimons

                        Will do, thanks for your interest.  If you find something that I have missed I will be in debt to you.   I have also put @BypassInterceptors on the getters and setters of the "currentResponseParagraph"; this did not seem to help.

                         

                        Here are relevant snippets, broken out by XHTML and Java.

                         

                        XHTML:

                         

                        -- Link to call action and open modal to edit the entity; verified that the right object is passed and store in the backing bean; I've also went the "action" route instead of the setPropertyActionListener route; both approaches seem to work identically

                        <a4j:commandLink
                                                                        id="cmdModifyParagraph"
                                                                        styleClass="add-table"
                                                                        ajaxSingle="true"
                                                                        reRender="modifyParagraphPopup"
                                                                        oncomplete="#{rich:component('modifyParagraphPopup')}.show()">
                                                                        <f:setPropertyActionListener value="#{_responseParagraph}"
                                                                                                     target="#{responseManager.currentResponseParagraph}"/>
                                                                        <ui:include src="#{formHelperBean.editBtnTemplate}">
                                                                            <ui:param name="buttonText" value="Edit"/>
                                                                        </ui:include>

                         

                                                                </a4j:commandLink>

                         

                        -- the modal panel; I've tried innumerable a4j:outputPanels, h:form instead of a4j:form, a4j:outputPanel around each input, no luck!

                         

                        <rich:modalPanel id="modifyParagraphPopup" minHeight="400" minWidth="500">
                            <f:facet name="header">
                                <h:outputText value="Modify Paragraph" />
                            </f:facet>
                            <a4j:form id="modifyParagraphForm">
                                <a4j:outputPanel id="modifyParagraphErrorPanel">
                                        <rich:messages id="modifyParagraphErrors"
                                                infoLabelClass="info-class"
                                                errorLabelClass="error-class"
                                                fatalLabelClass="fatal-class"
                                                warnLabelClass="warn-class"></rich:messages>
                                </a4j:outputPanel>
                                <a4j:outputPanel id="modifyParagraphInput" ajaxRendered="true">
                                    <h:outputText value="TEST #{responseManager.currentResponseParagraph.paraNumber}"/>
                                        <ui:decorate template="/layout/forms/table.xhtml">
                                            <tr>
                                                <s:decorate id="modifyNumberDecorate" template="/layout/forms/edit.xhtml">
                                                    <ui:define name="label">Paragraph Number:</ui:define>
                                                <h:inputText id="modifyParaNumber"
                                                             required="true"
                                                             requiredMessage="Paragraph Number is required"
                                                             converterMessage="Paragraph Number must be a number"
                                                             validatorMessage="Paragraph Number must be a number"
                                                             value="#{responseManager.currentResponseParagraph.paraNumber}"></h:inputText>
                                                </s:decorate>
                                            </tr>
                                            <tr>
                                                <s:decorate id="modifyTitleDecorate" template="/layout/forms/edit.xhtml">
                                                    <ui:define name="label">Paragraph Name:</ui:define>
                                                <h:inputText id="modifyParaName"
                                                             required="true"
                                                             requiredMessage="Paragraph Name is required"
                                                            value="#{responseManager.currentResponseParagraph.paraName}"></h:inputText>

                         

                                                </s:decorate>
                                            </tr>
                                            <tr>
                                                <s:decorate id="modifyLocationDecorate" template="/layout/forms/edit.xhtml">
                                                    <ui:define name="label">Location:</ui:define>
                                                    <h:inputText id="modifyParaLocation"
                                                        value="#{responseManager.currentResponseParagraph.location}"></h:inputText>
                                                </s:decorate>
                                            </tr>
                                            <tr>
                                                <s:decorate id="modifyDescriptionDecorate" template="/layout/forms/simpleEdit.xhtml">
                                                    <ui:define name="label">Description:</ui:define>
                                                    <h:inputTextarea id="modifyParaDescription"
                                                        value="#{responseManager.currentResponseParagraph.paraDescription}"
                                                            rows="4"
                                                            cols="40"></h:inputTextarea>
                                                </s:decorate>
                                            </tr>
                                        </ui:decorate>

                         

                                        <ui:decorate template="/layout/forms/action.xhtml">

                         

                                            <a4j:commandLink
                                                id="cmdSubmitManagedParagraph"
                                                styleClass="submit"
                                                data="#{facesContext.maximumSeverity.ordinal ge 2}"
                                                immediate="false"
                                                reRender="modifyParagraphErrorPanel,modifyParagraphPopup"
                                                oncomplete="if(data == false) Richfaces.hideModalPanel('modifyParagraphPopup');"
                                                action="#{responseManager.submitManagedParagraph}" >
                                                <h:graphicImage value="#{theme.imgdir}/buttons/submit.png"/>
                                                <h:outputText value="#{messages['form.button.submit']}"/>
                                            </a4j:commandLink>

                         

                                            <a4j:commandLink id="cmdCancelManagedParagraph" styleClass="cancel"
                                                             immediate="true"
                                                             action="#{responseManager.refresh}"
                                                             reRender="modifyParagraphPopup"
                                                             oncomplete="Richfaces.hideModalPanel('modifyParagraphPopup')">
                                                    <h:graphicImage value="#{theme.imgdir}/buttons/cancel.png"/>
                                                    <h:outputText value="#{messages['form.button.cancel']}"/>
                                            </a4j:commandLink>
                                        </ui:decorate>
                                </a4j:outputPanel>

                         

                            </a4j:form>
                        </rich:modalPanel>

                         

                         

                        -- Although I am not currently calling this method, I have tried calling the below method on the a4j:commandLink action to ensure that the proper object is set; both approaches work, but here is an example of this approach

                         

                        @Begin(join=true)
                            public void modifyParagraph(ResponseParagraph responseParagraph) {
                                log.info("modifyParagraph: id= " + responseParagraph.getParaName());
                                currentResponseParagraph = entityManager.find(ResponseParagraph.class, responseParagraph.getId());
                        //        cvParagraph = currentResponseParagraph;

                         

                         

                         

                            }