jeff
jeff

Reputation: 3732

Datatable link to edit record only works once unless I hit refresh

working with a Primefaces data table and dialog. Each record in data table has a link as such:

     <p:commandLink value="#{item.pk}" update=":itemUpdateForm:display"
                    onclick="PF('itemUpdateDialog').show();" title="Edit">
            <f:setPropertyActionListener value="#{item}"
                        target="#{itemController.selecteditem}" />
     </p:commandLink>

The link opens a primefaces dialog successfully the first time but after I submit the form in this popup dialog, which updates that recordset, the links in the datatable will no longer open the dialog again unless I hit refresh on the browser.

Here is the update button in the p:dialog:

<f:facet name="footer">
    <p:commandButton value="Update" update=":ItemListForm:dataTable, :growl"
        oncomplete=" handleSubmitRequest(xhr, status, args, 'itemDlg','itemUpdateForm');"
        actionListener="#{itemController.doUpdateItem()}" />
    <p:commandButton type="reset" value="Reset"></p:commandButton>
</f:facet>

And scopes/pertinent code:

itemController

@ManagedBean
@ViewScoped
public class ItemController implements Serializable {

@PostConstruct
public void init() {
    items= itemListProducer.getItems();
}

public void doUpdateItem() {
    itemRepository.update(selectedItem);
    itemEventSrc.fire(selectedItem);
    items = itemListProducer.getitems();
    Messages.addAjaxMessage("Update Operation Was Successful!");
}

List Producer

@ApplicationScoped
public class ItemListProducer implements Serializable {

Edit per comment here is DataTable and the Primefaces update dialog

<h:form id="ItemListForm">
    <p:dataTable id="dataTable" var="item"
        value="#{itemController.items}"
        paginator="true" rows="10"
        selection="#{itemController.selectedItems}" rowKey="#{item.oc_id}"
        paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
        lazy="false" rowsPerPageTemplate="10,15,50">

   <f:facet name="header"> 
       Items (#{itemController.items.size()}) 
   </f:facet>

   <p:column selectionMode="multiple" style="width:18px"/>

   <p:column filterBy="#{item.oc_id}" sortBy="#{item.oc_id}">
      <f:facet name="header"><h:outputText value="OC #" /></f:facet>

      <p:commandLink value="#{item.pk}" update=":itemUpdateForm:display" onclick="PF('itemUpdateDialog').show();" title="Edit">
      <f:setPropertyActionListener value="#{item}" target="#{itemController.selecteditem}" />
      </p:commandLink>
   </p:column>

   more p:columns

   <f:facet name="footer">
      <p:commandButton value="New item" onclick="PF('dlg1').show();" title="Creates new Item" />

      <p:commandButton value="Delete Selected Items" 
         actionListener="#{itemController.doDeleteItems}"
         update="@form, :growl">
        <p:confirm header="Confirmation" message="Are you sure you want to remove the selected Items?" />
      </p:commandButton>
  </f:facet>

</p:dataTable>
    <p:confirmDialog global="true">
        <p:commandButton value="Yes" type="button"
            styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
        <p:commandButton value="No" type="button"
            styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
    </p:confirmDialog>

</h:form>

... and dialog

<p:dialog header="Item Update Form" widgetVar="itemUpdateDialog" resizable="false" id="itemDlg">
   <h:form id="itemUpdateForm">
      <p:panel>
         <p:panelGrid id="display" columns="3" cellpadding="4"
                    style="margin:0 auto;">

                    <h:outputText value="Title :"></h:outputText>
                    <p:inputText id="title" value="#{itemController.selectedItem.title}"
                        required="true"
                        requiredMessage="Please Enter Title!" />
                    <p:message for="title" />
    other inputs

                    <f:facet name="footer">
                        <p:commandButton value="Update" update=":ItemListForm:dataTable, :growl"
                            oncomplete=" handleSubmitRequest(xhr, status, args, 'itemDlg','itemUpdateForm');"
                            actionListener="#{itemController.doUpdateItem()}" />
                        <p:commandButton type="reset" value="Reset"></p:commandButton>
                    </f:facet>
         </p:panelGrid>
      </p:panel>
   </h:form>
</p:dialog>

EDIT 2 Thanks to help from Michele's Answer, I determined the issue was related to how I was closing the dialog by its id and not by its widgetVar. I was originally passing in just the id which was used with jQuery effect 'shake', and then closing that object. By adding the widgetVar and using Michele's var d = (typeof dialogWv === "string") ? PF(dialogWv) : dialogWv; I no longer have my issue.

This ultimately works for me:

<p:dialog header="Update Form" widgetVar="itemUpdateDialogWv"
    resizable="false" id="itemUpdateDialogId">
      <h:form id="itemUpdateForm">
          <p:panel>
  ------content-------
                <f:facet name="footer">
                    <p:commandButton value="Update" update=":ItemListForm:dataTable, :growl"
                        oncomplete=" handleSubmitRequest(xhr, status, args, 'itemUpdateDialogWv','itemUpdateForm', 'itemUpdateDialogId');"
                        actionListener="#{itemController.doUpdateItem()}" />
                    <p:commandButton type="reset" value="Reset"></p:commandButton>
                </f:facet>
            </p:panelGrid>
            </p:panel>

      </h:form>
</p:dialog>


function handleSubmitRequest(xhr, status, args, dialogWv, formName, dialogNameId) {  
        dialog = jQuery('#'+dialogNameId);
        var d = (typeof dialogWv === "string") ? PF(dialogWv) : dialogWv;
    if(args.validationFailed) {  
        dialog.effect("shake", { times:5 }, 1000);  
    } else {
        clearForm(formName);
        d.hide();
    }  
}
function clearForm(formName){
    jQuery('#'+formName).each(function(){
        this.reset();
});
}

Upvotes: 0

Views: 600

Answers (1)

Michele Mariotti
Michele Mariotti

Reputation: 7469

Too long for a comment...

You can try:

<p:commandLink value="#{item.pk}" process="@this" update=":itemUpdateForm" 
    oncomplete="PF('itemUpdateDialog').show();" title="Edit">

    <f:setPropertyActionListener value="#{item}" target="#{itemController.selecteditem}" />
</p:commandLink>
  • specify process="@this": otherwise it defaults to @all and will include the dialog too
  • use oncomplete instead of onclick

and

<p:commandButton value="Update" process="@form" update="@form, :ItemListForm, :growl"
    oncomplete="handleSubmitRequest(xhr, status, args, 'itemDlg','itemUpdateForm');"
    actionListener="#{itemController.doUpdateItem}" />
  • specify process="@form": the same as before
  • add @form to update: generally is a good practice to update the dialog form tho show validation errors and to close dialog only if not validation failed (I don't know how handleSubmitRequest works, maybe it does exactly this)

However:

  • No js errors on commandButton click?
  • Is request fired?
  • If yes, can you post request params for the not working click?

P.S.

handleSubmitRequest(xhr, status, args, 'itemDlg','itemUpdateForm'); has argument itemDlg. Is it correct?

for completeness here is my hideDialog

function hideDialog(dialog, args, status, xhr)
{
    var d = (typeof dialog === "string") ? PF(dialog) : dialog;

    if(!args.validationFailed)
    {
        d.hide();
    }
}

which is invoked:

<p:commandButton value="Update" process="@form" update="@form :ItemListForm :growl"
    oncomplete="hideDialog('itemUpdateDialog', args)"
    actionListener="#{itemController.doUpdateItem}" />

Upvotes: 1

Related Questions