1
votes

I have a particular set of components (primefaces lazy loaded data table, and a p:messages) which are being updated via partial rendering in an ajax request. I have configured the messages component to be updated on the datatable's page event, but it seems that the messages component is always updated before the datatable, unless I place it below the datatable component within it's respective form.

Here's a summary of the jsf page configuration; I also have a bit of code which adds a message to the faces context within the "load" method of the #{lazyDataModel} backing bean, and on inspecting the partial response (and screen results), this message is added to the update for 'msgsAfter', but not to 'msgsBefore'.

<h:form id="reviewRoomsForm">
    <p:messages id="msgsBefore" globalOnly="true" showDetail="true" />
    <p:dataTable id="hotelRooms" var="room" value="#{lazyDataModel}" paginator="true" 
                 rows="10" emptyMessage="#{msg.noRecordsFound}">
        <p:ajax event="sort" update=":reviewRoomsForm:msgsBefore :reviewRoomsForm:msgsAfter" />
        <p:ajax event="page" update=":reviewRoomsForm:msgsBefore :reviewRoomsForm:msgsAfter" />

        ...

    </p:dataTable>
    <p:messages id="msgsAfter" globalOnly="true" showDetail="true" />
    <br />
</h:form>

I'm wondering, is there any way (JSF2 or Primfaces-specific) to control the order in which components are updated on a partial render? Alternatively, if I can't explicitly specify the order of updates, is there a way to convey that one component depends on another (and so should be updated after the other one)? My ultimate goal is to have the messages displayed at the top of the page, even when errors occur during partial update such as in lazy-paging table.

Things I've tried:

  • Re-ordering the component IDs in the "update" attribute; doesn't seem to matter. It looks like the order of iteration is controlled by the parent component's getFacetsAndChildren()
  • Adding a p:remoteCommand to be fired in the "oncomplete" client event for the page event to update the messages manually; fires in the correct order, but the message is no longer in FacesContext at this point.

Edit: This appears to be a possible bug in the primefaces component, in that it fires the "load" event on the lazyDataModel during the RENDER_RESPONSE phase, instead of the UPDATE_MODEL_VALUES phase. If it happened to update it's model values during the UPDATE_MODEL_VALUES phase, there would be no problem with rendering the error messages appropriately.

1
If the answer below solved your issue, please mark it as accepted. Thx.BestPractices

1 Answers

2
votes

LazyDataModel#load(...) is invoked during the RENDER RESPONSE phase. You unfortunately, will not be able to place Messages in this method and have them display for the msgsBefore component which comes before the data table. If you can move the logic to create the Faces Messages to a location earlier in the JSF lifecycle, say in the listener method for the page event, then your messages will display for both the msgsBefore component and the msgsAfter component.

If you cannot do that, the following should work for you (works for me):

<p:ajax event="page" 
        update=":reviewRoomsForm:msgsBefore :reviewRoomsForm:msgsAfter"
        oncomplete="$('#reviewRoomsForm\\\\:beforeMessage').html($('#reviewRoomsForm\\\\:afterMessage').html())"