Conditional update in Primefaces/jsf - ajax

First of all, so that there are no misunderstandings, while this is the same question as PrimeFaces: conditional update on validation I am asking it again, because the answer to that question is not acceptable to me, because while it may have given the original poster a workaround for what they were asking, it doesn't really answer the question, and this workaround doesn't work for me.
So, here's my question: how do I conditionally update a primefaces component based on the results of the submition?
I have a component that must not, under any circumstances be updated UNLESS the validation is successful and backend code was executed successfully. (i.e. if the validation succeeds but there was an SQL exception on the back end, the component still shouldn't be updated).
Why can't I always update it? If the logic doesn't succeed it'll be updated to the same thing it was before the submit button was clicked. Because I can't. It's the captcha component. If you update it via ajax, it disappears, end of story. There was a ticket opened at Primefaces and they closed it as won't fix, because flash compoents aren't supposed to be updated w/ ajax.
So when I submit the form, unless the logic succeeds I need to leave the captcha alone. IF the logic succeeds, I need to make sure the captcha disappears off screen. What's the easiest, cleanest way to do it?
Excuse me if this is a n00b question. I'm really new to Primefaces and JSF.

RequestContext.getCurrentInstance().update("clientId")
Helps for conditional updates.
For recaptcha try
RequestContext.getCurrentInstance().execute("Recaptcha.destroy()");

You can use a combination of JavaScript and RemoteCommand:
<p:commandLink action="#{bean.doIt()}" process="#form" update="#none" oncomplete="if(!args.validationFailed){updateMyImportantUI();}" />
<p:remoteCommand name="updateMyImportantUI" process="#this" update=":myImportantID" />

You can use a variable at the backing bean and use it on the xhtml part.
Like this:
update="#{backingMB.updateString}"
So, after the condition you can put the value for updateString, but when you define it on the backingMB, you need to put it as:
String updateString=""; // this will be id of the component to be updated
This way you won't get a NullPointerException.

Related

Page not updating after ajax call

I have a custom component (that is, an xhtml file with ui:composition inside) where I have a file upload field. When a file is selected it is uploaded via AJAX like this
<uc:fileUpload
id="#{id}fileUploadComponent"
idSuffix="#{id}fileUploadSuffix"
value="#{fileUpload.docsFilePart}"
accept="#{fieldWrapper.acceptedFileTypes}"
widgetVar="#{id}documentUploadWidget"
nullAllowed="#{!((fieldDef.mandatory and
fieldWrapper.getCurrentFileCount() lt 1) and isSaving)}"
maxSize="#{customField.maxFileSize}" >
<f:ajax listener="#{fileUpload.uploadNewFile(fieldWrapper)}" render="#{localId}fileUploadMain messages"/>
</uc:fileUpload>
Below this upload there's a <div> with the same id as specified in the render attribute of the ajax call, where links for downloading the files are shown. What happens is weird - after a file is selected, it is uploaded, the <div> is updated correctly with a link to the newly uploaded file. However when I click "Cancel" or "Save" on the page, their according actions are called, a correct response is returned to the browser (with status 200) but the browser seems to ignore it - the page is not visually updated or anything...
The custom component is quite big piece of code with not-so-easy-to-rewrite logic so replacing it at this point will be... hard...
One thing to not might be that uploading the file happens in a separate controller, while the main page controller is another one. This is because the separate controller is supposed to handle uploads from the custom component.
I can't really understand what exactly happens, even less why, and I'll appreciate any ideas!
For what it's worth, I am using Mojarra on Wildfly 11 (the one provided by the AS)
As it turns out, the reason is that file uploading via JSF AJAX causes the creation of an iframe called "JSFFrameId" and that frame being set as the target of the nesting form. After the AJAX request completes the target is not removed/cleared thus causing responses to go into that iframe and breaking the view.
At this point I am not sure what causes this, but a workaround for me is to have onevent in the <f:ajax> definition, that clears the form target, like this:
<f:ajax
listener="#{fileUpload.uploadNewFile(fieldWrapper)}"
onevent="function(e){if (e.status == 'complete') { $(e.source).parents('form').attr('target','');}"
render="#{localId}fileUploadMain messages">
I will check what other states may need handling but basically this solves the problem. It may be useful if someone shares their suspicions on what may have caused JSF to leave behind this iframe and not reset the target of the form.

Form values not submitted, reset on ajax

In my current project I have a construct, where you have an entity where you can change the values through a approval workflow.
If you want to save a new version of an entity, you click on a button and a dialog pops up. There you can set the one to approve your change and an additional, optional comment.
My problem is, that the values from this dialog are not submitted.
The dialog is included in my main template, but outside of the main form. The dialog is appended to the Body, like this:
<p:dialog id="idEntityCommentDialog"
header="#{msgs['label.approval.dialogHeader.'.concat(bean.targetStatus)]}"
width="350" widgetVar="entityCommentDlg" modal="true"
maximizable="false" resizable="false" appendTo="#(Body)">
Both fields set their value to an object inside the sessionScoped backing bean:
<p:selectOneMenu id="selUsers"
value="#{bean.state.releasedBy}" style="width: 100%">
<f:selectItems value="#{bean.fetchUserList()}" var="user"
itemValue="#{user.id}"
itemLabel="#{user.name}" />
</p:selectOneMenu>
<p:inputTextarea id="changeComment"
value="#{bean.state.newComment.eventDescription}"
style="width: 98%; height: 100px">
<f:converter converterId="xssConverter" />
</p:inputTextarea>
Before, I had standard jsf controls, h:sekectOneMenu and h:inputTextArea. I have switched to the respective primefaces controls, and now at least the value from the selectOneMenu is submitted, but still, the value from the inputTextarea is not submitted. I have set breakpoints in the used converter, and I receive an empty string in my converter, which works in different other places where I use it.
I tried various combinations of update parameters and I also tried to set the value in an ajax request via
<p:ajax event="change" update="#this">
When I use the p:ajax tag, I can see, that when I change the value, after the ajax request, the value is immediately reset to the original value before the change. This applies for both fields (when using the standard controls) Like I said, I fixed it with the primefaces control (I don't understand why, but it seems to work) but it doesn't work for the inputTextArea.
My button is inserted with a toolbar facet from primefaces.
<p:commandButton actionListener="#{bean.saveEntity}"
styleClass="toolbarButton" update="dialogForm2 :blocker:contentWrapper"
onstart="PF('waitDialog').show();"
oncomplete="PF('waitdialog').hide();PF('entityCommentDlg').hide();"
value="#{msgs['label.approval.button.'.concat(bean.targetStatus)]}">
</p:commandButton>
The form is defined inside the dialog with just an id:
<h:form id="dialogForm2">
I am mostly confused, that if I use the p:ajax control, that my value is reset immediately, so there must be something very wrong here.
I also checked that I have no failed validations that I maybe don't see for some reason (via a phaseListener) but that's not the case, no facesMessages occur.
Please respect that I can't show you complete chunks of code from the project, my customer wouldn't want that, but if you need further information about other code or architecture, I will try to provide it. I also changed some ids and names, but I made sure that they are correct and referenced properly in the original code.
Do you have any idea what could be the reason for this kind of behaviour?
I know there are various articles about form values not submitted, I have seen them and tried the solution, but nothing seems to work for me here. A colleague of mine also has no idea why it shouldn't work. I use nearly the same construct (with a different backing bean and objects) in another part of the application, there, everything works fine, with the standard jsf controls.
Ok, I finally found the problem. The solution was to remove appendTo="#(Body)"
I had very strange behaviour before I found the solution.
You see, in the onStart and onComplete events of the submit button, I display a loading overlay. The bug occured as I fixed this loadingOverlay. Before I had a copy&paste error, where I referenced the wrong loading overlay, which was not present in the current page. But the bug only occured when I used the correct overlay or I even deleted the reference to this overlay completely. When I put in the wrong id of the overlay again, it worked...
Now, when I removed the appendTo attribute, everything seems to work fine, even the correct loading overlay. I don't even know anymore why I used the appendTo attribute. I assume the dialog was in another place before and I had to use it, but meanwhile the dialog is placed directly in the body of the document, outside of any layout or form, so I understand that I don't need it.
Does someone has a more educated idea why this error happened like it did? I understand that appendTo can have side effects when you don't need to use it, but the general behaviour I could observe here is beyond any reason to me.

Wicket RadioGroup, AjaxFormChoiceComponentUpdatingBehavior, Form Submit?

I got a RadioGroup in Wicket with an AjaxFormChoiceComponentUpdatingBehavior added.
Upon triggering the change, the behavior is sending a POST, but other changes on the parent form are not sumbitted.
My question is: What is the correct way to achieve a complete submit?
(I need the complete form submit because there's other stuff going on with the form)
I do not think that there is a standard wicket way to do this.
Would "pressing" an AjaxSubmitButton using JavaScript work for you?
Maybe someting like this?
onchange="$('button.mysubmit').click();"
(assuming that you have an AjaxSubmitButton with the CSS class mysubmit)

Keeping a rich:modalPanel open on validation fail?

I'm trying to keep my modal from closing when validation, done with an actionLister, fails.
I've seen numerous discussions on this issue with several purposed solutions but have had no luck with any of them. Anyone have any working solutions?
I'm using RichFaces 3.3.3.Final.
Have you tried this?
oncomplete="if (#{!validation.failed}) Richfaces.hideModalPanel('accounts_popup1');"
I love StackOverflow because I always find the solution immediately after posting a question.
The first solution in http://community.jboss.org/wiki/ModalPanelValidation works for me.
Paraphrased, put an id on your h:messages element and then do this Javascript check to see if you can close the modal.
function modalClose() {
if (!document.getElementById('fullresolvedidofmessagepanel')) {
Richfaces.hideModalPanel('modalpanelid');
}
}
The strings here are stand ins.
Yup - in the oncomplete(..) function of your button verify whether the facesContext contains any errors. If not - hide(), otherwise do nothing.

How to prevent ajax driven form from being submitted twice?

I am taking my first steps with Ajax while working on a Grails application. I am using
<g:form ...>
<g:submitToRemote ... />
</g:form>
in the most simple way and it worked great out of the box (Thanks grails!). The problem is, that the Ajax call needs about 2 seconds to return and update the html (at least on the test system) and during that time, the user can (and actually does quite often) hit the submit button again. At the moment this results in a 2nd call being made that finally ruins the output (an error msg says, that one cannot submit the same data twice).
What is the best way to prevent this?
Thanks in advance for your input!
The best way to handle this is to disable the submit button in your onSubmit() function. Honestly, I don't know why more sites don't do this. I often go the next step and instead of disabling the submit button, I put the submit button in a span tag and replace the contents of the span tag with static text "Please wait..." That way your users get visual feedback they pressed the button and "top men are working on it".
As dj_segfault said you can do that.
If you want to validate this in your controller, take a look in "Handling Duplicate Form Submissions" in the official docs:
http://grails.org/doc/latest/guide/theWebLayer.html#formtokens

Resources