I have multiple command buttons in my JSF ... Its a database search which has one 'Search' button and the other 'Add' button.
When clicking on 'Search' Button i wanted a status to be displayed, so i added the below ajaxStatus code to my outputPanel which is in form1 where my search results are displayed.
<p:ajaxStatus onstart="statusDialog1.show();" onsuccess="statusDialog1.hide();"/>
Dialog Box
<p:dialog modal="true" widgetVar="statusDialog1" header="Searching ... Please wait"
draggable="false" closable="false" resizable="False">
<p:graphicImage value="/resources/ajax-loader.gif" />
</p:dialog>
When the 'Add' button is clicked, another dialog box opens which has form2, now the problem is when i click on 'Add' Button statusDialog1 is shown as well, i want that status to be shown only when 'Search' button is clicked.
How do i use multiple agaxStatus messages in the same page ?
From the dev guide
AjaxStatus is a global notifier for ajax requests.
In other words, you will have one per page which handles all ajax processing on that page. If you are using PrimeFaces p:commandButton you can use the onstart and onsuccess attribute of your Add and Search button. Example:
<p:commandButton value="Add" onstart="statusDialog1.show();" onsuccess="statusDialog1.hide()"/>
<p:commandButton value="Search" onstart="statusDialog2.show();" onsuccess="statusDialog2.hide()"/>
Another thing you can use to "show" the ajax status of each component is PrimeFaces <p:blockUI>. You can refer to the showcase for some examples
Related
Using JSF and PrimeFaces 6.1 I have an inputText field as such:
<p:inputText value="#{backingBean.stringField}">
<p:ajax event="valueChange" update="#form" />
</p:inputText>
and within the same form is a commandButton:
<p:commandButton id="btnDoThatThing"
ajax="true"
immediate="true"
update="#form"
process="#this"
action="#{backingBean.doThatThing}"/>
When I
make a change to the inputText field,
then click somewhere OTHER THAN the command button
click the command button
everything works exactly as expected. BUT if I:
make a change to the inputText field,
immediately the command button
The button is NOT fired since the first click of the commandButton is triggering the valueChange event to happen in the inputText field.
If I click it a second time the button action finally happens.
Now, if i change the p:ajax event="valueChange" to p:ajax event="keyup" the first click of the commandButton work as expected, but unfortunately the keyup event on a inputField is pretty hacky and you lose functionality within the field (copy/paste text, text selection, 'fast' typing' etc)
Any thoughts on how to initiate the change event in the inputText field, AND fire the commandButton action when the user clicks the button immediately from typing in the inputText field?
First your valueChange is triggered. This updates the form including the button. Not 100% sure if this is browser dependent, but in Chromium (Linux), the click on the previously rendered button (before it has been updated) is not executed.
I could get it working when I changed the update expression into a selector. My expression updates the elements I needed to be updated excluding the button(s). In my case:
<p:ajax update="#(form :input:not(button))" />
Note that the change event is default for inputs, so I've removed event="valueChange".
Of course you do not need to use a selector. You can also just update a component (like a panel) which does not contain the button:
<p:ajax update="yourPanel" />
Also, ajax="true" is default for a p:commandButton, so you can remove that.
In my case, I solved the same problem removing the following statement from my page (Primefaces 11.0):
<p:ajaxStatus onstart="PF('statusDialog').show()" onsuccess="PF('statusDialog').hide()"/>
Somehow the onstart event overrides the click event and only one event is processed: change.
I have primefaces datatable
<p:dataTable ...>
<p:ajax event="rowSelect" update=":previewDataForm" oncomplete="$('.previewDataModal').modal();"
immediate="true">
</p:ajax>
</p:dataTable>
And modal in which I would like to display PDF (b tag is bootsfaces)
<b:modal id="previewDataModal" title="Preview" styleClass="orderPreviewModalPseudoClass">
<h:form id="previewDataForm">
<pe:documentViewer height="550" value="#{contentStreamHelperBean.pdfFromFileSystem}" rendered="#{previewMB.renderPreview}"/>
</h:form>
</b:modal>
I have problem with displaying it in case on ajax call from dataTable. When I have attribute update=":previewDataForm" on rowSelect then PDF is displayed, but it's rendered twice and buttons in documentViewer are not responding. When I remove update=":previewDataForm" from rowSelect documentViewer is not rendered.
When I invoke this modal with commandButton, then everything works ok.
Is there way how to render previewDataForm only once and then display it from ajax?
Thanks
The modal is rendered when the page is displayed first. In other words, it's rendered before the user has selected a row. I suggest you add a rendered= condition to the <h:form> tag to prevent the initial rendering of the PDF file. My guess is that the PDF file can't be rendered because no row has been selected (typically a NullPointerException), and that this leads to follow-up errors.
I have created a JSF application using Myfaces 2.1.12 and Richfaces 4.3.3. On normal browsers the application works fine, but the client insists that he also needs to use a "browser" - IE8, version 8.0.7601. I am having a bunch of problems.
I have a rich:extendedDataTable on the main form. Clicking a row is to open a popup with the details (that is rendered and filled with the data from the selected row). The popup can also be called from a toolbar, this way it displays the details of the row that was selected when the page was first loaded.
The table is defined as follows (column definition removed for clarity)
<h:form>
<rich:extendedDataTable id="table" rowClass="row" rows="15"
value="#{scheduleController.allSchedules}" var="schedule" selectionMode="single"
selection="#{scheduleListBean.selectedSchedule.selection}" clientRows="15">
<a4j:ajax render="scheduleDetails, toolbar, transferListPopup" event="selectionchange"
listener="#{scheduleController.scheduleSelectionChanged}"
oncomplete="#{rich:component('scheduleDetailsPopup')}.show()"/>
...
</rich:extendedDataTable>
</h:form>
The popup contains a couple of panel grids, one of wich contains some buttons.
<h:panelGrid columns="2" styleClass="alignTop" id="scheduleDetails">
...
<rich:panel header="#{generalProperties.controls}">
<h:panelGrid columns="4">
<a4j:commandLink styleClass="btn" type="button"
render="table#body, transferDetailsPanel, destinationPanel, datesPanel"
oncomplete="if (#{facesContext.maximumSeverity == null}) #{rich:component('scheduleDetailsPopup')}.hide()"
status="pleaseWait" action="#{scheduleController.saveSchedule}"
value="#{generalProperties.save}" />
<h:commandButton class="btn" action="#{scheduleController.changeScheduleStatus}"
value="#{applicationProperties.changeStatus}" status="pleaseWait" type="button"
disabled="#{scheduleController.currentSchedule.id == null}">
<rich:componentControl target="changeScheduleStatusPopup" operation="show" />
</h:commandButton>
<h:commandButton class="btn" value="#{generalProperties.delete}" status="pleaseWait" type="button"
disabled="#{scheduleController.currentSchedule.id == null}">
<rich:componentControl target="removeSchedulePopup" operation="show" />
</h:commandButton>
<a4j:commandButton styleClass="btn" type="button"
render="fileTable, transferDetailsPanel, destinationPanel, datesPanel"
disabled="#{scheduleController.currentSchedule.id == null}"
oncomplete="if (#{facesContext.maximumSeverity == null}) #{rich:component('transferListPopup')}.show()"
status="pleaseWait" value="#{applicationProperties.transferHistory}" />
</h:panelGrid>
</rich:panel>
</h:panelGrid>
The disabled="#{scheduleController.currentSchedule.id == null}" part checks the bean if anything is selected as the popup is also used to add new rows.
Everything works fine on firefox. On IE8:
clicking the commandLink does not work(nothing happens, besides a "#"
that is appended to the url in the browser) when the popup is called from the
extended data table (rendered), but works when it is called from the
toolbar.
clicking the commandButton does not work(page is reloaded instead of an ajax request beeing executed) when the popup is called from the extended data table (rendered), but works when it is called from the
toolbar.
if I remove the type="button" from command buttons, then clicking them causes the entire page to be reloaded
What am I missing?
The answer was in the question itself. I rebuilt the UI so that no buttons are rendered in ajax requests. This way it works both on IE 8 and IE 9.
Ie.: Instead of setting the disabled attribute based on a bean and rendering the buttons I had to use two instances of each of those buttons. I did that by extracting a form into a composite component using composite:insertChildren just to inject buttons in the proper state and having two instances of the form on the page, showing the right one when the user clicked new schedule / edit schedule.
The drawback of this method is that I had to set the render attribute of the components that show the popup to something different then forms (in this case - panels), which would be an issue if I used Mojarra (see this question: javax.faces.ViewState is missing after ajax render)
I have a required input field in a p:dialog. If firstly I submit nothing for the field, a validation error happens on that field. Then I close the dialog and reopen it, the validation error still exists. What can I do to eliminate the validation error when close the dialog?
You should use the p:resetInput on the element that you have to open the dialog.
For example if you use a p:commandButton
<p:commandButton value="Open dialog" update=":dialogId" oncomplete="PF('dialogWidget').show()" >
<p:resetInput target=":dialogId" />
</p:commandButton>
This will reset the cached values (including the validation messages) upon opening the dialog.
I was able to reproduce your case and you could do the following:
Make your dialog closable="false".
Add a Cancel button that will hide the dialog.
Add a resetInput component from Primefaces Extensions inside your Cancel button. This will clear the form validations and values.
Here is an example that assumes your dialog as a widgetVar named wvDialog.
<p:commandButton value="Cancel" immediate="true" onclick="wvDialog.hide()">
<pe:resetInput for="myDialogFormId />
</p:commandButton>
You could even call a bean method in the button actionListener if you need.
I hope it helps.
Update the p:dialog or p:message every time you submit the Form.
You can do that by using update attribute of p:commandButton.
<p:commandButton update="ID_OF_DIALOG" />
I have noticed that pretty much all PF components that have 'dynamic' attribute set to 'true' will only show up after a short delay (which is understandable), and also will not trigger ajax start/stop event.
This is my (perfectly working) Ajax status component, actual dialog contents omitted for brevity:
<p:ajaxStatus onstart="statusDialog.show();" onsuccess="statusDialog.hide();" onerror="errorDialog.show();"/>
This is a dynamically loaded dialog. It needs to get data from backing beans:
<p:dialog modal="true" widgetVar="confDialog" position="center" id="confD" dynamic="true">
<p:panelGrid>
<p:row>
<p:column>
<h:outputText value="Date"></h:outputText>
</p:column>
<p:column>
<h:outputText value="#{myBean.currentDate}">
<f:convertDateTime locale="#{myBean.currentLanguage}" type="both" dateStyle="full" timeStyle="full" timeZone="#{myBean.currentTimeZone}"></f:convertDateTime>
</h:outputText>
</p:column>
</p:row>
</p:panelGrid>
<p:commandButton value="Close" type="button" onclick="confDialog.hide();">
</p:commandButton>
</p:dialog>
A commandbutton that does something and displays dynamically loaded confirmation dialog:
<p:commandButton value="Do it" type="submit" ajax="true" process="#form"
action="#{bean.processForm}"
oncomplete="if(!args.validationFailed){confDialog.show();}"
update="confD #form"/>
Ajax status dialog is displayed while the commandbutton submits the data to backing bean and gets data back. Then ajax status dialog disappears, there is a delay of 1-2 seconds, and confirmation dialog is shown.
The same happens with dynamically loaded tabs (in PF tabView component).
Why isn't my ajax status dialog displayed during dynamic component load? How can I show it?
EDIT:
thanks to #partlov I figured out a solution without overriding PF function, by adding JQ ajax start/stop handler to the dynamically loaded dialog:
jQuery(document).ready(function() {
confDialog.getJQ().ajaxStart(function(){statusDialog.show()});
confDialog.getJQ().ajaxStop(function(){statusDialog.hide()});
});
As written in Primefaces documentation <p:ajaxStatus> just intercepts global AJAX requests, and this request is not global. There is no easy way to do this what you want. As time of loading of dialog is short I really don't see point for this. Only solution, as I think, is to overload Primefaces dialog JavaScript methods.
Primefaces calls loadContents() method when dialog content is loaded so you can override this method for this. I don't advice you to do that, because this is undocumented and can be changed in future versions of Primefaces:
jQuery(document).ready(function() {
var oldLoadContents = PrimeFaces.widget.Dialog.loadContents;
PrimeFaces.widget.Dialog.loadContents = function() {
statusDialog.show();
oldLoadContents();
}
});
This should show your dialog on dynamic loading. You can use onShow attribute of p:dialog to close your dialog:
onShow="statusDialog.hide()"