0

I have a dataTable with a list of items and a checkbox for selecting an item to edit. Ticking an item and clicking the edit button pops up a component which has fields and update and cancel buttons. Here's what happens.

  1. Dialog appears
  2. I empty all fields and click UPDATE, required messages appear since all fields are empty, data is not saved
  3. Click CANCEL, dialog disappears
  4. Click and edit the same item again
  5. Some fields are not showing. I checked the datatable and database, data for the item still exists. Just not showing on the edit dialog the 2nd time around.

I noticed that the fields not showing are only those that have NULL attributes. NOT NULL fields are fine. I wonder if this has something to do with sessions. (Using Primefaces for all components)

Code for the edit dialog

<p:dialog header="#{bundle.Edit}" modal="true" widgetVar="editDialog" resizable="false">
        <h:form id="edit-form">
          <p:messages id="edit-error" autoUpdate="true" closable="true"/>
          <h:outputLabel value="#{bundle.Name}" for="name" /><span class="required">*</span>
          <p:inputText id="name" value="#{controller.selected.name}" required="true" requiredMessage="#{bundle.Name}&nbsp;#{bundle.FieldIsRequired}" maxlength="45"/>
          <h:outputLabel value="#{bundle.Input}" for="input" /><span class="required">*</span>
          <h:selectOneRadio id="input" value="#{controller.selected.input}" required="true" requiredMessage="#{bundle.Input}&nbsp;#{bundle.FieldIsRequired}">
            <f:selectItem itemLabel="◯ " itemValue="0" />  
            <f:selectItem itemLabel="☓ " itemValue="1" />  
          </h:selectOneRadio>
          <h:outputLabel value="#{bundle.IsOption}" for="isOption" /><span class="required">*</span>
          <h:selectOneRadio id="isOption" value="#{controller.selected.isOption}" required="true" requiredMessage="#{bundle.IsOption}&nbsp;#{bundle.FieldIsRequired}">
            <f:selectItem itemLabel="◯ " itemValue="0" />  
            <f:selectItem itemLabel="☓ " itemValue="1" />   
          </h:selectOneRadio>
          <h:outputLabel value="#{bundle.Remark}" for="remark" />
          <p:inputTextarea id="remark" value="#{controller.selected.remark}"/>

          <p:commandButton action="#{controller.update()}" 
                           value="#{bundle.Save}" 
                           actionListener="#{controller.prepareList()}" 
                           oncomplete="handleEditDialog(xhr, status, args)" 
                           update=":form:datatable :edit-form:edit-error"
                           />
          <p:commandButton value="#{bundle.Cancel}" 
                           onclick="editDialog.hide(); reset();" 
                           type="button"/>
        </h:form>
      </p:dialog>



Code for the update function

public String update() {
    RequestContext context = RequestContext.getCurrentInstance();
    try {
      current.setUpdateDate(new Date());
      Map<String, Object> param = JsfUtil.getExternal().getSessionMap();
      int createUser = (Integer) param.get("LOGIN_ID");
      Account account = accountFacade.find(createUser);
      current.setUpdateUser(account);
      getFacade().edit(current);
      search();
      prepareList();
      JsfUtil.addSuccessMessage(ResourceBundle.getBundle(JsfUtil.getSessionBundle()).getString("Updated"));
      updateOk = true;
      current = null;
      context.addCallbackParam("updated", true);
      return "";
    } catch (Exception e) {
      if (e.getCause().getCause().getMessage().contains("uk_")) {
        JsfUtil.addErrorMessage("edit-form:edit-error",JsfUtil.getResourceString("Duplicate"));
        context.addCallbackParam("updated", false);
      } else {
        JsfUtil.addErrorMessage(e, ResourceBundle.getBundle(JsfUtil.getSessionBundle()).getString("PersistenceErrorOccured"));
        context.addCallbackParam("updated", false);
      }
      return null;
    }
  }
jmc
  • 1,649
  • 6
  • 26
  • 47
  • This is a classif JSF problem, take a look at this thread: http://stackoverflow.com/questions/2118656/hcommandlink-hcommandbutton-is-not-being-invoked/2120183#2120183 – mchamati Jul 01 '13 at 04:57
  • It could be anything but you won't get much help without code. Are you resubmitting/updating the form after you hit cancel so that the data can repopulate ? Are your buttons inside the form ? Are your listeners being called ? – Andy Jul 01 '13 at 07:59
  • @Andy I edited the post and added the code. **Are you resubmitting/updating the form after you hit cancel so that the data can repopulate?** - Cancel does nothing except closing the dialog. **Are your buttons inside the form ?** - Yes. **Are your listeners being called ?** - Yes. The code works just fine with a regular update. The bug will only exist when saving an empty form and pressing cancel. – jmc Jul 01 '13 at 09:39
  • Ok, I'll see what I can dig up. – Andy Jul 01 '13 at 10:48
  • Not quite yet. Giving that field a required attribute solves the problem but actually this field is not required. It is optional for users to input data or not. I also realized that it applies to all entries on the dataTable. Somewhat it saves the state of this unrequired field until a page refresh or a successfull update. – jmc Jul 02 '13 at 03:49

2 Answers2

0

Based on what you are describing I think the following scenario is happening. When you see the form and you delete all fields and you hit save, the components that have no validators are actually overwriting some of the previous property values of your bean. That's why when you reload it for a second edit, you'll notice that all the components that have a validator attached (e.g required = true) are appearing but those with no validators are blank. In reality, you are actually doing a partial update. What you actually need to do is mark all fields as required to avoid that problem.

Andy
  • 5,900
  • 2
  • 20
  • 29
0

My teammate just found out a fix for this one. There is a function on the controller generated by NetBeans called prepareList().

public String prepareList() {
    recreateModel();
    return "";
  }

private void recreateModel() {
    items = null;
  }

Basically we added this on catch block of the update() function. It is called after every unsuccessful update and recreates the model. The bug existed because the field retained its state of not having a value after an unsuccessful update.

jmc
  • 1,649
  • 6
  • 26
  • 47