Primefaces <p:blockUI> hidding growl <p:growl> after releasing - jsf

I'm trying to update message by clicking button from backing bean and in the same time after clicking button I'm trying to block this button to avoid doubleclick. Blocking occurs successfully and message appears, but after the unblocking message disappears. This happens pretty quickly. And I want the message in growl stay longer.
My .jsf snippet.
<h:form id="form">
<p:growl id="messages" />
<p:blockUI block="button" widgetVar="block"/>
<p:dataTable var="item" id="table" value="#{bean.lazyModel}"
lazy="true">
<p:column>
<p:commandButton value="#{item.actionBtn}"
update=":form:messages" action="#{bean.action}"
oncomplete="filterTableFromPanel();PF('block').hide()"
onclick="PF('block').show()">
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
In backing bean all just as usual.
public void action(){
FacesContext.getCurrentInstance().addMessage(null, msg);
}
Please, forgive me for possible mistakes, snipet is trimmed.

You have the option of setting the sticky or life:
sticky to keep the growl to stay visible until the user closes the growl component manually
life to set a timeout period for the component. This value will determine how long the message is visible for, and then it disappears after the life elapses. Set this value in milliseconds life="1200" (default is 6000)

I've resolved my problem using p:remoteCommand.
<h:form id="form">
<p:growl id="messages" />
<p:blockUI block="button" widgetVar="block"/>
<p:remoteCommand name="addMessage"
action="#{bean.addMessage}"
update=":form:messages" />
<p:dataTable var="item" id="table" value="#{bean.lazyModel}"
lazy="true">
<p:column>
<p:commandButton value="#{item.actionBtn}"
update=":form:messages" action="#{bean.action}"
oncomplete="filterTableFromPanel();PF('block').hide(); addMessage()"
onclick="PF('block').show()">
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
In backing bean I've add somethhing like this:
public void addMessage(){
FacesContext.getCurrentInstance().addMessage(null, "msg");
}

Related

P:CommandButton in popup dialog did not submit

I have encountered a strange situation.
I have a xhtml looks like this:
<h:form id="frmContent">
<p:dataTable id="tbl" ..>
</p:dataTable>
<p:contextMenu for="tbl">
<p:menuitem value="Delete" update="tbl" actionListener="#{VehicleBean.deleteVehicle}"/>
<p:menuitem value="Copy" update=":frmContent:vehicleDia:VehicleDialogContent" action="#{VehicleBean.copyVehicle}" oncomplete="PF('VehicleDialog').show();"/>
</p:contextMenu>
<p:dialog header="Vehicle Detail" widgetVar="VehicleDialog" modal="true" resizable="true" appendTo="#(body)">
<h:form id="vehicleDia">
<p:panelGrid id="VehicleDialogContent" columns="2" >
...
</p:panelGrid>
<p:commandButton id="SaveButton" type="button" value="Save" update="VehicleDialogContent" actionListener="#{VehicleBean.saveVehicle}" oncomplete="PF('VehicleDialog').hide();">
</h:form>
</p:dialog>
The problem is, I cannot make the VehicleBean.saveVehicle() method fired.
I have tried to remove the nested form "vehicleDia" but not work.
I have tried to changing actionListener to action but still not work.
I have tired using h:commandButton instead of p:commandButton still no lucky.
Right now, I dont have any clue.
PS: this is my bean:
#ManagedBean(name="VehicleBean")
#ViewScoped
public class VehicleBean {
...
public void saveVehicle() {
System.out.println("VehicleBean:saveVehcile is called");
}
}
I am new to JSF and primefaces, any help is much appreciated!!

Button in dialog inside p:dialog is not calling controller method

I've got a problem as described in the title.
Small description of the problem is as following:
I have button which is used to open dialog. Then, inside that dialog, there is button which opens another dialog on top of the first one. After clicking second button I want method from controller to be called but nothing happens. Value in h:outputText is read properly, so I guess it is not a problem with connection controller->view.
I'm using:
Spring web 3.1.2.RELEASE
JSF 2.2.10
Primefaces 5.1
Code:
beans.xml
<bean id="testController" class="test.TestController" />
TestController.java
public class TestController implements Serializable
{
private static final long serialVersionUID = 7028608421091861830L;
private String test;
public TestController()
{
test = "abc";
}
public void testMethod()
{
test = "cba";
}
public String getTest()
{
return test;
}
}
test.xhtml
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg1').show();" />
</h:panelGrid>
<p:dialog widgetVar="dlg1">
<h:outputText value="Resistance to PrimeFaces is futile!" />
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg2').show();" />
</h:panelGrid>
<p:dialog widgetVar="dlg2">
<h:outputText value="#{testController.test}" />
<p:commandButton value="Call method" type="button" actionListener="#{testController.testMethod}" />
</p:dialog>
</p:dialog>
What I tried:
adding appendToBody="true" to each p:dialog
changing from p:commandButton to p:button
changing from actionListener to action
but nothing helps.
I would be grateful for any help or advice of what can be the reason of not calling given method.
There are 3 problems.
You're nesting <p:dialog> components. This doesn't make sense. Separate them.
A <p:dialog> must have its own <h:form>, particularly when you explicitly use appendToBody="true" or appendTo="#(body)", otherwise nothing can be submitted because JavaScript would relocate the dialog out of its position in the HTML DOM tree to the end of body, causing it to not be sitting in a form anymore.
A <p:commandButton type="button"> acts as a "click" button, not as a submit button. Remove that attribute from submit buttons.
All in all, this is how it should look like:
<h:form>
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg1').show();" />
</h:panelGrid>
</h:form>
<p:dialog widgetVar="dlg1">
<h:form>
<h:outputText value="Resistance to PrimeFaces is futile!" />
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg2').show();" />
</h:panelGrid>
</h:form>
</p:dialog>
<p:dialog widgetVar="dlg2">
<h:form>
<h:outputText value="#{testController.test}" />
<p:commandButton value="Call method" actionListener="#{testController.testMethod}" />
</h:form>
</p:dialog>
OK. I guess I found a way to fix this problem.
It seems that the problem was:
type="button"
I deleted it from the list of attributes of each button and now it works even without h:form. Thanks for help.

Primefaces datatable update datatable

I have a problem with primefaces datatables. I have one datatable with some entries and a column with a button inside. If the button is pressed a popup is opened with another datatable. The entries in the second datatable are depending on the row in which the button is pressed.
<!-- first datatable -->
<h:form id="list">
<p:dataTable id="list1" var="item" value="#{bean1.itemlist}"
rowKey="#{item.id}" selection="#{bean1.selectedItem}"
selectionMode="single">
<p:column headerText="ID">
<h:outputText value="#{item.id}" />
</p:column>
...
<p:column headerText="Edit Entries">
<p:commandButton value="Edit Entries"
actionListener="#{bean2.updateEntries(item)}" ajax="true"
oncomplete="PF('edit_entries').show()" />
</p:column>
</p:dataTable>
<!-- Second datatable in the popup -->
<p:dialog header="Edit Entries" widgetVar="edit_entries" modal="true"
resizable="false">
<p:dataTable id="list2" var="entry"
value="#{bean2.entriesList}" rowKey="#{entry.id}"
selection="#{bean2.selectedEntry}" selectionMode="single">
<p:column headerText="Entry Number">
<h:outputText value="#{entry.number}" />
</p:column>
</p:dataTable>
<f:facet name="footer">
<p:commandButton value="Save" oncomplete="PF('edit_entries').hide()" />
</f:facet>
</p:dialog>
</form>
Bean2
public void updateEntries(Item selectedItem) {
this.entriesList = this.entriesQuery.getAllEntriesByItemID(selectedItem.getId());//db query could take some time
System.out.println("entrieslist size: " + this.entriesList.size()); //prints the correct size
}
The problem is that there are no entries listed in the popup datatable although there are some in the list after the db query.
Any ideas how to fix this bug?
Thanks in advance!
UPDATE 1:
<!-- first datatable -->
<h:form id="list">
<p:dataTable id="list1" var="item" value="#{bean1.itemlist}"
rowKey="#{item.id}" selection="#{bean1.selectedItem}"
selectionMode="single">
<p:column headerText="ID">
<h:outputText value="#{item.id}" />
</p:column>
...
<p:column headerText="Edit Entries">
<p:commandButton value="Edit Entries" update=":dialogUpdateEntries"
actionListener="#{bean2.updateEntries(item)}" ajax="true"
oncomplete="PF('edit_entries').show()" />
</p:column>
</p:dataTable>
</h:form>
<!-- Second datatable in the popup -->
<p:dialog header="Edit Enries" id="dialogUpdateEntries" widgetVar="edit_entries" modal="true"
resizable="false">
<h:form id="formEntriesList">
<p:dataTable id="list2" var="entry"
value="#{bean2.entriesList}" rowKey="#{entry.id}"
selection="#{bean2.selectedEntry}" selectionMode="single">
<p:column headerText="Entry Number">
<h:outputText value="#{entry.number}" />
</p:column>
</p:dataTable>
<f:facet name="footer">
<p:commandButton value="Save" oncomplete="PF('edit_entries').hide()" />
</f:facet>
</form>
</p:dialog>
You're indeed not updating the data table in the dialog. JSF doesn't automatically update the view on change of the model, you have to explicitly tell the view to do so. You can use the ajax action component's update attribute for this. This takes a JSF client ID which can be found by rules as outlined in this related answer: How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar".
Given the markup as shown in the question, that'll be
<p:commandButton ... update=":list:list2" />
However, there's another potential problem. You're using <p:dialog modal="true"> inside a form instead of giving the dialog its own form. This way the dialog may not be available in the HTML DOM tree as JavaScript (the one responsible for dealing with ajax stuff) would expect to find it. Giving the dialog its own form should fix this matter. It'll also fix the potential future problems with invoking actions from inside the dialog as handled in this related question: <p:commandbutton> action doesn't work inside <p:dialog>.
<h:form id="viewForm">
...
<p:commandButton ... update=":editDialog" />
...
</h:form>
<p:dialog id="editDialog" modal="true">
<h:form id="editForm">
...
</h:form>
</p:dialog>
Try adding update="list2" to Edit Entries command button (even update="#widgetVar(edit_entries)" should work).
If, because of page layout and structure, you can't target the second datatable using above suggestions, then add styleClass="tList2" to second table, and update it with update="#(.tList2)" on edit button.

Getting a NullPointerException while Partial rendering via FacesContext

I have a strange behavior where I am getting NPE while doing page refresh using faces context.
I have a managed bean which is in Request Scope. So want to refresh the page after click on commandbutton. I have tried with 'update' but it is behaving strange in my page.
Error: PartialViewContextImpl$PhaseAwareVisitCallback.visit : java.lang.NullPointerException
This is my JSF page:
<h:form id="form">
<p:messages autoUpdate="true"/>
<h:panelGrid columns="4" cellpadding="5" id="panelGrid" rendered="true">
<p:outputLabel for="s00" value="#{tk.expense_keyword}"/>
<p:inputText id="s00" value="#{expense.form.keyword}"/>
<p:outputLabel for="s02" value="#{tk.expense_creatorId}"/>
<p:inputText id="s02" value="#{expense.form.creatorId}" disabled="#{!expense.form.canEditCreatorId}"/>
<h:outputText id="s10" value="Amount Between #{expense.form.amountFrom} and #{expense.form.amountTo}" />
<h:panelGrid>
<p:slider for="s11,s12" display="s10" minValue="0" maxValue="1000" style="width: 200px" range="true" displayTemplate="Amount Between {min} and {max}" />
<h:inputHidden id="s11" value="#{expense.form.amountFrom}" />
<h:inputHidden id="s12" value="#{expense.form.amountTo}" />
</h:panelGrid>
</h:panelGrid>
<p:commandButton value="#{tk.expense_search}" id="a01" action="#{expense.search}" ajax="false" immediate="true"/>
<p:dataTable var="line" varStatus="loop" value="#{expense.form.expenseEntryList}" emptyMessage="#{tk.expense_table_empty}" id="dataTable">
<p:column headerText="#{tk.expense_table_creatorId}">
<h:inputHidden value="#{line.oid}"/>
<h:inputText value="#{line.creatorId}"/>
</p:column>
<f:facet name="footer">
<p:commandButton value="#{tk.expense_saveAsDraft}" id="a06" action="#{expense.saveAsDraft}"/>
<p:commandButton value="#{tk.expense_submit}" id="a07" action="#{expense.submitAll}"/>
<p:commandButton value="#{tk.expense_validate}" id="a08" action="#{expense.validate}"/>
</f:facet>
</p:dataTable>
</h:form>
Here when I click on Save As Draft I want to refresh the page. So I am using FacesContext's method to refresh the page.
Here is my method saveAsDraft:
public Outcome saveAsDraft() throws Exception{
try {
saveAsDraftBody(false,false);
getFacesContext().getPartialViewContext().getRenderIds().add("form:panelGrid");**//**getting error****
getFacesContext().getPartialViewContext().getRenderIds().add("form:dataTable");**//**works fine****
Log.info(this,"getFacesContext().getPartialViewContext().getRenderIds(): "+getFacesContext().getPartialViewContext().getRenderIds());
return Outcome.SUCCESS;
}
catch (Throwable e){
throw manageError(e);
}
}
I don't know why it works for data table refresh but not for panelGrid :(
First of all you have the bean in request scope and you are making full page submit and here the partial render does not make any sense. The error you are getting because you have component which is basically, another input into a form which will be sent to the managed bean of the current view when the form is submitted.

Open <p:dialog> from bean by RequestContext#execute()

I have this form with a panel grid and a dialog:
<h:form id="regiForm">
<p:panelGrid>
<p:row style="height:30%">
<p:column>
<h:outputText/>
</p:column>
<p:column>
<p:commandButton style="width:350px" type="submit" actionListener="#
{regiBean.showDialog}" id="ajax" value="#{msg['regi_button']}" update="regiForm" process="#this"/>
</p:column>
<p:column>
</p:column>
</p:row>
</p:panelGrid>
<p:dialog id="dialog" header="#{msg['regi_dialog_header']}" widgetVar="myDialog" position="center center" >
<h:outputText value="#{msg['regi_dialog']}" />
</p:dialog>
</h:form>
I would like to open the dialog from inside the action listener:
public void showDialog() {
RequestContext.getCurrentInstance().execute("dialog.show()");
RequestContext.getCurrentInstance().execute("myDialog.show()");
}
However, the dialog is not shown. How is this caused and how can I solve it?
I'm using JSF 2.1 and PrimeFaces 3.5.
The first statement with the command
RequestContext.getCurrentInstance().execute("dialog.show()");
won't work because dialog refers to the XHTML ID of the p:dialog component. This will cause an javascript error. And that could be the reason why the second command
RequestContext.getCurrentInstance().execute("myDialog.show()");
won't get executed.
Also I would add ; to the end of each Javascript command (but this is just my personal style)

Resources