jsf - <f:ajax render="@none" execute="@this"> and reducing submitted post data size in large form -
i have huge jsf-page underlying viewscopebean contains large form (containing 100 inputs) many ajaxified input fields. every input field, submit current value , render nothing. sample field in form:
<h:selectbooleancheckbox id="includeforeigncurrencies" value="#{ratingmanagerbean.formdata.foreigncurrencies}" action="#{ratingmanagerbean.calculate}"> <f:ajax render="@none" execute="includeforeigncurrencies"/> </h:selectbooleancheckbox>
after ajax post inspect e.g. developer tools in firebug , recognize submitted size of post data 2 kb. select row, choose "copy post data" , pasted editor:
every field of form submitted although interested in current changed field:
form-search=form-search countrycode=at ratingtype={"type":"country"} averagerating minamount maxamount averageamount company location staffresponsible staffresponsible2 requestdate reminderdate acutalcurrency comparecurrencies //70 other empty form-ids.... includeforeigncurrencies=on javax.faces.viewstate=1825148886808299106:-354534052529224349 javax.faces.source=includeforeigncurrencies javax.faces.partial.event=click javax.faces.partial.execute=includeforeigncurrencies javax.faces.behavior.event=valuechange javax.faces.partial.ajax=true
is there way reduce posted data like:
includeforeigncurrencies=on javax.faces.viewstate=1825148886808299106:-354534052529224349 javax.faces.source=includeforeigncurrencies javax.faces.partial.event=click javax.faces.partial.execute=includeforeigncurrencies javax.faces.behavior.event=valuechange javax.faces.partial.ajax=true
or just
includeforeigncurrencies=on
thanks in advance!
workaround:
as possible workaround came disabling inputs did not trigger post , re-enable them in ajax complete. post data size 200 b instead of 2000 b.
as not sure if may cause other issues, update of question, not answer.
<h:selectbooleancheckbox id="includeforeigncurrencies" value="#{ratingmanagerbean.formdata.foreigncurrencies}" action="#{ratingmanagerbean.calculate}" onclick="prepareajaxpost(this)"> <f:ajax render="@none" execute="includeforeigncurrencies" onevent="ajaxpostcomplete"/> </h:selectbooleancheckbox>
javascript/jquery:
function prepareajaxpost(source){ //keep disabled inputs disabled $("#form-search :input:not(:disabled)").filter(function() { return !this.id.match(/javax.faces.viewstate/); //all inputs ignoring jsf- viewstate ones }).each(function(){ var input = $(this); var others = input.not(source); others.attr("disabled", true); others.addclass("blocked"); //some style has no visual effect users }); } function ajaxpostcomplete(data) { switch (data.status) { case "success": { $("#form-search :input.blocked").each(function(){ $(this).attr("disabled",false).removeclass("blocked"); }); break; } }
start reading 'edit 2:' @ end
i know question jsf 2.3, out of curiosity, wanted see if possible @ in plain jsf. , thing seems possible @ least mojarra 2.2.8 (did not have other environments @ hand quickly) overriding jsf.js function. and... if want 'conditional', not on every input/button/..., add passthrough attribute.
i checked/debugged sourcecode of mojarra jsf.js file , noticed possible strip/filter out fields after full querystring created instead of primefaces way prevent fields added 'upfront'. function can done getviewstate , overriding this, calling original 1 , adding logic before returning result, seems work. downside might filter out (see comment @ end)
the js add code (make sure loaded after jsf.js)
partialsubmit.js
var orgviewstate = jsf.getviewstate; jsf.getviewstate = function(form) { var myviewstate = orgviewstate(form); var eventsource = this.ajax.request.arguments[0]; // read partialsubmit input (mojarra puts attributes without camelcasing in html, pt:partialsubmit in xhtml becomes partialsubmit in html var partialsubmit = eventsource.attributes['partialsubmit']; //if not on input, check form if (partialsubmit === undefined) { partialsubmit = form.attributes['partialsubmit']; } if (partialsubmit != undefined && partialsubmit.value === "true") { var params = myviewstate.split("&"); var kvpairs = []; var ids = []; // create list of id's based on 'execute' list var execute = this.ajax.request.arguments[2].execute; // todo check other replacements (@parent, @form)? execute = execute.replace('@this', eventsource.id); execute = execute.replace('@none', ""); var ids = execute.split(" "); for(j=0;j<ids.length;j++) { var id = ids[j]; (i=0;i<params.length; i++) { var kv = params[i].split("="); if (kv[0] === kv[1] || //to pass on form id value keypair. not sure needed kv[0] === "javax.faces.viewstate" || // check if other 'relevant' fields need passed on (viewid, conversationid etc... how detect these? encodeuricomponent(id) === kv[0]) { kvpairs.push("&"+params[i]); } } } return kvpairs.join(""); } else { return myviewstate; } }
and example of usage provided below. in example first , last input fields have pt:partialsubmt="true"
added inputs (could not work when added ajax tag). there 2 ajax enabled h:commandbuttons
, 1 , 1 without partial submit. using browser developer tool can see differences when using them
partialsubmitdemo.xhtml
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui" xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"> <h:head /> <h:body> <!-- adding pt:partialsubmit="true" form makes work every input/button in form --> <h:form> <h:panelgrid columns="4" border="1" id="panel"> <h:outputtext value="label" /> <h:outputtext value="input" /> <h:outputtext value="single ajax" /> <h:outputtext value="all ajax" /> <h:outputlabel value="inp0" /> <h:inputtext value="#{sessionscope['inp0']}" id="inp0" pt:partialsubmit="true"> <f:ajax render="aout0" execute="@this" /> </h:inputtext> <h:outputtext value="#{sessionscope['inp0']}" id="aout0" /> <h:outputtext value="#{sessionscope['inp0']}" id="out0" /> <h:outputlabel value="inp1" /> <h:inputtext value="#{sessionscope['inp1']}" id="inp1"> <f:ajax render="aout1" execute="@this" /> </h:inputtext> <h:outputtext value="#{sessionscope['inp1']}" id="aout1" /> <h:outputtext value="#{sessionscope['inp1']}" id="out1" /> <h:outputlabel value="inp2" /> <h:inputtext value="#{sessionscope['inp2']}" id="inp2"> <f:ajax render="aout2" execute="@this" /> </h:inputtext> <h:outputtext value="#{sessionscope['inp2']}" id="aout2" /> <h:outputtext value="#{sessionscope['inp2']}" id="out2" /> <h:outputlabel value="inp3" /> <h:inputtext value="#{sessionscope['inp3']}" id="inp3"> <f:ajax render="aout3" execute="@this" /> </h:inputtext> <h:outputtext value="#{sessionscope['inp3']}" id="aout3" /> <h:outputtext value="#{sessionscope['inp3']}" id="out3" /> <h:outputlabel value="inp4" /> <h:inputtext value="#{sessionscope['inp4']}" id="inp4"> <f:ajax render="aout4" execute="@this" /> </h:inputtext> <h:outputtext value="#{sessionscope['inp4']}" id="aout4" /> <h:outputtext value="#{sessionscope['inp4']}" id="out4" /> <h:outputlabel value="inp5" /> <h:inputtext value="#{sessionscope['inp5']}" id="inp5"> <f:ajax render="aout5" execute="@this" /> </h:inputtext> <h:outputtext value="#{sessionscope['inp5']}" id="aout5" /> <h:outputtext value="#{sessionscope['inp5']}" id="out5" /> <h:outputlabel value="inp6" /> <h:inputtext value="#{sessionscope['inp6']}" id="inp6"> <f:ajax render="aout6" execute="@this" /> </h:inputtext> <h:outputtext value="#{sessionscope['inp6']}" id="aout6" /> <h:outputtext value="#{sessionscope['inp6']}" id="out6" /> <h:outputlabel value="inp7" /> <h:inputtext value="#{sessionscope['inp7']}" id="inp7"> <f:ajax render="aout7" execute="@this" /> </h:inputtext> <h:outputtext value="#{sessionscope['inp7']}" id="aout7" /> <h:outputtext value="#{sessionscope['inp7']}" id="out7" /> <h:outputlabel value="inp8" /> <h:inputtext value="#{sessionscope['inp8']}" id="inp8"> <f:ajax render="aout8" execute="@this" /> </h:inputtext> <h:outputtext value="#{sessionscope['inp8']}" id="aout8" /> <h:outputtext value="#{sessionscope['inp8']}" id="out8" /> <h:outputlabel value="inp9" /> <h:inputtext value="#{sessionscope['inp9']}" id="inp9" pt:partialsubmit="true"> <f:ajax render="aout9" execute="@this" /> </h:inputtext> <h:outputtext value="#{sessionscope['inp9']}" id="aout9" /> <h:outputtext value="#{sessionscope['inp9']}" id="out9" /> </h:panelgrid> <h:commandbutton value="update ajax partial submit" pt:partialsubmit="true"> <f:ajax render="out0 out1 out2 out3 out4 out5 out6 out7 out8 out9" execute="@this" /> </h:commandbutton> <h:commandbutton value="update ajax full submit"> <f:ajax render="out0 out1 out2 out3 out4 out5 out6 out7 out8 out9" execute="@this" /> </h:commandbutton> <h:commandbutton value="clear all" pt:partialsubmit="true"> <f:setpropertyactionlistener value="" target="#{sessionscope['inp0']}" /> <f:setpropertyactionlistener value="" target="#{sessionscope['inp1']}" /> <f:setpropertyactionlistener value="" target="#{sessionscope['inp2']}" /> <f:setpropertyactionlistener value="" target="#{sessionscope['inp3']}" /> <f:setpropertyactionlistener value="" target="#{sessionscope['inp4']}" /> <f:setpropertyactionlistener value="" target="#{sessionscope['inp5']}" /> <f:setpropertyactionlistener value="" target="#{sessionscope['inp6']}" /> <f:setpropertyactionlistener value="" target="#{sessionscope['inp7']}" /> <f:setpropertyactionlistener value="" target="#{sessionscope['inp8']}" /> <f:setpropertyactionlistener value="" target="#{sessionscope['inp9']}" /> <f:ajax render="panel" execute="@this" /> </h:commandbutton> </h:form> <script src="partialsubmit.js" type="text/javascript" /> </h:body> </html>
you can see comments in javascript code needs optimization working start/beginning.
edit:
- added option add
pt:partialsubmit="true"
<h:form>
using form wide - investigated passing on of existing request params using omnifaces
<o:form includerequestparams="true">
, not stripped due them not being in 'viewstate' key-value pairs of form fields.
edit 2:
the great omnifaces project have in upcoming 3.0 release. a commit has been made @balusc closed issue 394 created there result of question. within 5 days using
<o:form>
will default partialsubmit
Comments
Post a Comment