Rendering other form by ajax causes its view state to be lost, how do I add this back?
This is a known problem in the auto-included jsf.js
library of JSF which handles ajax responses. See also JSF spec issue 790 which is fixed in the upcoming JSF 2.3. In the meanwhile, with JSF 2.0/2.1/2.2, you have to explicitly specify the ID of the other <h:form>
inside the render
attribtue to trigger proper addition of the view state.
<h:form> <h:commandLink action="#{my_fake_ajax_link}"> <h:outputText value="Link" /> <f:ajax render=":mydiv :mydivForm" /> </h:commandLink></h:form><h:panelGroup layout="block" id="mydiv"> <h:form id="mydivForm"> <h:commandLink action="#{mybean.delete(0)}"> <h:outputText value="Here" /> <f:ajax render="@form" /> </h:commandLink> </h:form></h:panelGroup>
No, this does not cause any overhead or markup duplication in the ajax response. Alternatively, use OmniFaces fixviewstate.js
.
See also:
Workaround for that:
First you need to set an onevent
handler for the button that sends the ajax request:
<h:form id="newComment"> <h:commandButton id="saveNewComment" action="#{postBean.actionSaveNewCommentAjax}" value="#{rb['speichern']}"> <f:ajax execute="@form" render=":commentsBox" onevent="function(data) { fixOtherFormsViewState(data, 'newComment') }" /> </h:commandButton></h:form>
Then you need to declare this javascript methods that will take the correct viewState value and add it to all forms which doesn't have it:
<h:outputScript>function fixOtherFormsViewState(data, goodFormId) { if (data.status != "success") { return; } var viewState = jQuery("#" + goodFormId + " input[name='javax.faces.ViewState']").val(); jQuery("form:not(:contains(input[name='javax.faces.ViewState']))").each(function (idx, elem) { var form = jQuery(elem); var input = jQuery("<input type='hidden' name='javax.faces.ViewState' />").val(viewState); form.append(input); });}</h:outputScript>