im downloading a file from pentaho and it works, the problem is when I got actionlistener and
inside I call to javascript, it does not work, all code from backbean RequestContext.getCurrentInstance() are ignored
<p:commandButton widgetVar="fileexcelButton"
icon="fa fa-file-excel-o" styleClass="GreenBack"
update="#([id$=formPrincipal],[id$=growl]) "
process="#this #form" ajax="false"
actionListener="#{Bean.reportactionlistener}">
<f:attribute value="XLSX" name="tipo" />
<p:fileDownload value="#{bean.DefaultStreamedContentReport}" />
</p:commandButton>
back bean code
public void reportactionlistener(ActionEvent evt) throws Exception
{
RequestContext.getCurrentInstance().execute("PF('fileexcelButton').disable();");
imprimirReciboHistoricoventas(evt); //<- only this code is execute
RequestContext.getCurrentInstance().execute("PF('TablePanel').show()");
RequestContext.getCurrentInstance().execute("PF('TablePanelLoad').close()");
}
I also try using PrimeFaces.current().ajax().update
The button is working in this way, because I download the file from pentaho but the manage of UI from back bean or using properties to disable the button to avoid a lot of clicks and several API calls ignored.
onclick
if I enable onclick like this
onclick="PrimeFaces.monitorDownload(start, stop);"
it disables actionListener,but Js comeback and works but i never get the file from pentaho and also I tried to change actionlistener to Action but i get errors like NoSuchMethodException.
Related
In BootStrap calling a backend bean via AJAX does not seem to work for the DateTimePicker component.
If I am wrong with my code, could anybody please help?
To my surprise also the DateTimePicker reference page of BootStrap does not work with AJAX. On the reference page (https://showcase.bootsfaces.net/forms/DateTimePicker.jsf)
the reference code
<b:form>
<b:dateTimePicker value="#{test.dataToPick}" ondtchange="ajax:test.updateTestField()" process="#this" update="#next" label="Select date:" iconAwesome="bolt" />
<b:inputText value="#{test.testField}" label="Result: " readonly="true" />
</b:form>
is also not working.
Here is my code that is not working:
<b:form>
<b:dateTimePicker value="#{listBean.editMonth}"
readonly="false"
allow-input-toggle="false"
icon-position="right"
mode="popup"
format="MMM YYYY"
side-by-side="false"
show-date="true"
show-time="false"
show-icon="true"
required="true"
viewMode="months"
locale="en"
iconSize="xs"
styleClass="datePicker"
id="monthpicker"
process="#this"
ondtchange="ajax:listTradesBean.updateMonth()"
onblur="ajax:listTradesBean.updateMonth()"/>
</b:form>
Normally I would expect that the backend code "updateMonth()" would be called. The java code snippet for the backend bean simply is:
public void updateMonth() {
System.out.println("WORKING!");
}
Other methods within this backend bean are called without problems using AJAX.
You are right, the example in the Bootsfaces showcase page does not work.
Strangely enough, I managed to build a working example that solves your problem by using the traditional JSF AJAX (legacy) syntax:
<b:dateTimePicker id="datePicker"
format="DD/MM/YYYY HH:mm"
value="#{testBB.selectedDate}"
required="true"
renderLabel="false"
ajax="true"
process="#this"
update="#this"
ondtchange="#{testBB.doSomething()}">
</b:dateTimePicker>
As far as I know, this will work the same way as "ajax:testBB.doSomething()".
I have a p:dialog with a text input. When saving, the entered value is passed to an external service which may either accept or reject it. The text input has a validator, but that validator can only check so much. In particular, it does not know the external service's state. It cannot make a call to that service either cause between the checking time and saving time the input may become invalid.
So far, I have a <h:messages> in the page and in the popup. The popup is in its own form. The external service's validation error appears in the page's <h:messages> as the popup is closed because as a workaround I added the page's messages to the command button's update attribute. The popup's p:commandButton uses ajax='true' and a check for validation errors (oncomplete="if (arg && !arg.validationFailed) PF('popup').hide()") as explained in another post. It looks like validation is finished and there are no errors, so the popup closes and the button's actionListener runs to push the input to the external service, and then the error is returned from the service.
I understand that validating in a setter or listener is an anti-pattern, but I don't see a way around it here. It's not so much validating anyway, it's more a "take this" and being prepared to receive an error for it.
I tried opening the popup again from the listener but that did not open the dialog.
<h:form id="Form">
<h:messages id="pageErrors"/> <!-- external service error shows up here -->
<h:form>
<h:form>
<p:dialog widgetVar="popup">
<h:messages id="popErrors"/> <!-- I'd like to show the external service error here -->
<p:inputTextarea id="it" required="true"/>
<!-- required works as expected: error in the popup when nothing is entered, popup remains open -->
<p:commandButton value="Save it" ajax="true" update="popErrors Form:pageErrors"
oncomplete="if (args && !args.validationFailed) PF('popup').hide();"
actionListener="#{bean.saveIt}"/>
</p:dialog>
</h:form>
And the actionListener:
public void saveIt(#SuppressWarnings("unused") ActionEvent e) {
String error = extService.saveIt(it);
if (error != null) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(error)); // gets the error in the page's messages
facesUtil.showDialog("popup");
}
}
How can I keep this dialog open when the actionListener detects an error from the external service?
If I understand the problem this works for me:
update="popErrors :Form:pageErrors"
and
FacesContext.getCurrentInstance().validationFailed();
right after you add the message.
Adding a FacesMessage to the response is not the same as that the validation has failed. If you validate yourself, you must manually tell the framework if it failed.
You could also add your own callback parameter as Hatem suggests, but to my knowledge there is no problem reusing validationFailed.
I have two forms (one for some filter-settings, and the other for the content)
If I set some filter settings in the first form (e.g. "show only not empty chapters") with
<h:form>
<!-- some checkboxes -->
<h:commandButton value="Save filter settings" id="filterBUtton">
<f:ajax event="click" execute="#form" render="#all" listener="#{bean.saveFilter}"/>
</h:commandButton>
</h:form>
and try to execute a actionlistener from the second form (e.g. to display all found chapters), it doen't execute the command as ajax request (the view is lost somehow?) - and then my Filters say "stop! you are not an ajax request, so you can't pass here"
here is my second form (which is, like the first one, received from template):
<h:form>
#{bean.foundChapters} have been found. Show them now?
<h:commandButton value="Show them!" id="showThem">
<f:ajax event="click" render=":result" listener="#{bean.loadAndShowChapters}"/>
</h:commandButton>
</h:form>
<h:panelGrid id="result">
<!-- List of results... -->
</panelGrid>
here is my second method which makes the view crash (and is not submitted by ajax) (the first has a similar interface):
public void loadAndShowChapters(AjaxBehaviorEvent event){
System.out.println("force:true");
forceLoad = true;
doQuery(); //does the loading (so the results can be displayed in
}
The funny thing is that if I move the 'showThem' Button from form 2 to form 1, it works fine. Seems it has problems handling two forms? Two forms can't be a problem, am I right?
Can anyone help here pls?
thanks for your anwser,
I have solved it by
adding a ID to the form and
solve a Javascript-problem (it tried to find a element by document.getElementById('notExistantForm:element') onclick. After correctly defining the id, it worked again!
I have a form in the view "createDbUser.xhtml" with some input texts and validations like this:
<h:form>
<h:inputText id="user_name" value="#{dbUserManager.userName}" required="true" requiredMessage="User name is required." />
<h:inputSecret id="password" value="#{dbUserManager.password}" required="true" requiredMessage="Password is required." />
<h:commandButton id="create_user" value="Create user" action="#{dbUserManager.createUser()}" />
</h:form>
dbUserManger is a viewScoped managed bean with createUser() like this:
public String createUser()
{
...
// here I do some checks and add the new user to database
...
return "/restricted/createDbUser.xhtml?faces-redirect=true";
}
When I press the refresh button of my browser while some of the validations failed (e.g. I didn't enter password or username), I got "confirm form resubmission" instead of expected behaviour, i.e. reloading the page and clearing the inputs.
I've read about post-redirect-get pattern and that's why I added the return statement with "faces-redirect=true" parameter to the outcome of createuser().
I guess when validation failed we never get to the createuser() and consequently the return statement. And that's the cause of this problem. But I don't know how to solve it.
It would be very nice if some one help to solve the issue.
thanks
you are right:
When validation errors are recognized on server side during JSF LifeCycles Validation Phase, your action method is never called (being in the invoke phase later on).
What I would see as possible solutions: Try doing the validation client-side - for e.g. checking if login/pw exists, this could be achived via javascript triggered by h:commandButtons onclick-attribute. I'm not sure if you use any *Faces-framework above JSF2, but e.g. Richfaces4 also allows clientside validation without changing any code.
Another possible solution might be to send the form via AJAX, changing
<h:commandButton action="#{dbUserManager.createUser()}" />
to something like
<h:commandButton action="#{dbUserManager.createUser()}">
<f:ajax execute="#form" render="#all" />
</h:commandButton>
Here you might need to figure out how to manage the redirect to another screen in case of a correct login.
Hope, these ideas might push you further towards achieving your goals...
The supported JSF 2.x feature of sequential processing of multiple ajax-events doesn't work for me.
I got the following scenario:
h:inputText (CHANGE)
<h:inputText id="consumption_input"
value="#{cc.attrs.consumptionInfo.consumption}">
<f:ajax
render="#{cc.attrs.outerRenderString}"
event="change" listener="#{cc.handleAjaxRequest}" />
</h:inputText>
h:commandButton (ACTION)
<h:commandButton
id="startComparisonButton"
action="#{rateComparisonBean.startRateComparison()}"
value="#{bundle.rateResultOverview_startComparison}">
<!-- This is to avoid mixed requests, ajax and full requests -->
<f:ajax render="#form"/>
</h:commandButton>
The events of both elements are handled correctly if triggered on it's own.
Problem occurs when both events are triggered within one click (Enter a value in textInput and afterwards click on the button). I expected this lead to two ajax request fired synchronously (CHANGE-TextField and ACTION-commandButton).
Unfortunatelly there's only one Ajax-Request (Change-TextField), the second event seems to be lost completely.
I already ensured that all pre-conditions for a h:commandButton are full filled, as pointed out here:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated
I would appreciate to get any hints on how to solve this problem.
Environment:
Glassfish 3, Mojarra 2.1.3-FCS
The JSF AJAX calls are asynchronous. Sending one AJAX request, in this case generated by <h:inputText> onchange event, doesn't stop JavaScipt to continue its execution and, in this case, trigger submit button click, which in its turn fires another AJAX request. Still, AJAX requests are really queued on the client, to be processed in the exact order that they were sent, which is guranteed by JSF 2.0 specification, chapter 13.3.2.
Below is my test case:
The view:
<h:form id="form">
<h:inputText id="text" value="#{q16363737Bean.text1}">
<f:ajax render="text2" event="change" listener="#{q16363737Bean.ajaxListenerText}"/>
</h:inputText>
<h:commandButton id="button" action="#{q16363737Bean.actionButton}" value="Submit">
<f:ajax render="text1 text3" listener="#{q16363737Bean.ajaxListenerButton}"/>
</h:commandButton>
<br/>
<h:outputText id="text1" value="Text 1: #{q16363737Bean.text1}."/>
<h:outputText id="text2" value="Text 2: #{q16363737Bean.text2}."/>
<h:outputText id="text3" value="Text 3: #{q16363737Bean.text3}."/>
</h:form>
The bean:
#ManagedBean
#ViewScoped
public class Q16363737Bean implements Serializable {
private String text1 = "I'm text 1";//getter + setter
private String text2 = "I'm text 2";//getter + setter
private String text3 = "I'm text 3";//getter + setter
public void ajaxListenerText(AjaxBehaviorEvent abe) {
text2 = "I was modified after inputText AJAX call";
}
public void ajaxListenerButton(AjaxBehaviorEvent abe) {
text1 = "I was modified after AJAX listener call of commandButton";
}
public void actionButton() {
text3 = "I was modified after commandButton AJAX call";
}
}
After examining the question for some time I indeed figured out that very rarely the command button's AJAX call had been swallowed and no UI updates were done. It seems that there should be some race conditions somewhere. It is a great question and it needs to be investigated further.
So, this is probably not an answer (although I thought it would be initially), but a proposition for a test case. And despite the fact that I faced this behaviour very infrequently, it is a real use case, and it's worth fully understanding what's going on.
First thanks allot for the fast and sophisticated reply.
A second test from the scratch pointed out that ajax-events are queued properly.
So again I checked the more complex scenario described above. The cause for the skipped event seams to be related to our 'busy overlay'. Think of it as a bunch of JavaScript which disables form-elements and applies an overlay during long runing ajax requests. This is done by applying an jsf.ajax.addOnEvent call-back.
Anyway, even we disable some controls, after 'success' the form is in a proper state and the second event could be handled.
Currently I assume that the 'temporarily' disabled button compromises the related action event which should be carried out afterwards.
We are currently analyzing the issue and I will post the final result asap.