Primefaces blockUI stops working after ajax update

2019-01-20 08:32发布

问题:

I am trying to create a datatable that displays a blockUI whenever it is busy, and I have been mostly successful. It now grays out and shows "Loading..." whenever I click either of two commandButtons, sort the datatable by clicking on a header, or page through the datatable. You can see the code for it below.

The problem is that after I have used one of the commandButtons (which runs an ajax update on the blocked element), subsequent actions do not trigger the blockUI (until I refresh the page). For example:

  • Load page
  • Click a datatable header - blockUI appears until table is finished sorting
  • Click one of the datatable page navigation buttons - blockUI appears until the page is loaded
  • Click one of the commandButtons - blockUI appears until the button's actionListener has finished
  • Click a datatable header - table sorts, but blockUI does not appear.
  • Click one of the datatable page navigation buttons - page loads, but blockUI does not appear
  • Click one of the commandButtons - actionListener runs and table updates, but blockUI does not appear
  • Reload the page - everything works properly again

Changing the commandButtons' update="" attribute to ajax="false" causes the sorting/paging to always display the blockUI, but the commandButtons to never display the blockUI.

Any ideas?

<div class="buttonDiv">
    <p:commandButton ... update="resultsPanel" id="submitButton" ... />
    ...
    <p:commandButton ... update="resultsPanel" id="resetScenarioButton" ... />
</div>
<p:panel header="Results Grid" id="resultsPanel">
    ...
    <p:dataTable ... id="VAResults" ... >
        ...
    </p:dataTable>
    ....
</p:panel>
<p:blockUI block="resultsPanel" trigger="submitButton, resetScenarioButton, VAResults">
    Loading...
</p:blockUI>

回答1:

The trigger attribute binds jQuery listeners on the specified elements. However if you update an element the binding gets lost. I don't know if it works, but you could try moving the <p:blockUI inside the resultsPanel. I suspect that when you update the panel the blockUI gets updated too and thus re-binding the listener to the data table.

<p:panel header="Results Grid" id="resultsPanel">
    ...
    <p:dataTable ... id="VAResults" ... >
        ...
    </p:dataTable>
    ....
    <p:blockUI block="resultsPanel" trigger="submitButton, resetScenarioButton, VAResults">
    Loading...
</p:blockUI>
</p:panel>


回答2:

I've had the same problem and kind of simillar scenario:

<p:dataTable>
    ....
    <p:ajax event="rowSelect" update="buttons" global="false" onstart="blockMessageButtons.show();" oncomplete="blockMessageButtons.hide();"/>
</p:dataTable>

<p:outputPanel layout="block" id="buttons">
    <!-- content to be blocked -->
</p:outputPanel>

<p:blockUI block="buttons" widgetVar="blockMessageButtons"/>

The problem was that panel buttons was both updated by ajax, and blocked by blockUI. I had to divide it in two:

<p:dataTable>
    ....
    <p:ajax event="rowSelect" update="buttons-content" global="false" onstart="blockMessageButtons.show();" oncomplete="blockMessageButtons.hide();"/>
</p:dataTable>

<p:outputPanel layout="block" id="buttons-container">
    <p:outputPanel layout="block" id="buttons-content">
        <!-- content to be blocked -->
    </p:outputPanel>
</p:outputPanel>

<p:blockUI block="buttons-container" widgetVar="blockMessageButtons"/>