< f:ajax render =“" @ none"执行="@ this"并以较大的形式减少提交的帖子数据的大小 [英] <f:ajax render="@none" execute="@this"> and reducing submitted post data size in large form

查看:112
本文介绍了< f:ajax render =“" @ none"执行="@ this"并以较大的形式减少提交的帖子数据的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个巨大的jsf页,其中包含一个底层ViewScopeBean,该ViewScopeBean包含一个非常大的表单(包含近100个输入),其中包含许多邻接的输入字段.对于每个输入字段,我仅提交当前值,并且不呈现任何内容.所以只是该形式的示例字段:

i have a huge jsf-page with an underlying ViewScopeBean that contains a very large form (containing nearly 100 inputs) with many ajaxified input fields. for every input field, i only submit the current value and render nothing. so just a sample field in that form:

<h:selectBooleanCheckbox id="includeForeignCurrencies" 
                         value="#{RatingManagerBean.formData.foreignCurrencies}"
                         action="#{RatingManagerBean.calculate}">

    <f:ajax render="@none" execute="includeForeignCurrencies"/> 

</h:selectBooleanCheckbox>

在ajax发布后,我检查了开发人员使用firebug工具,并确认提交的帖子数据大小最大为 2 kb .然后我选择该行,选择复制发布数据"并将其粘贴到编辑器中:

after the ajax post i inspect e.g. the developer tools in firebug and recognize that the submitted size of the post data is up to 2 kb. then i select the row, choose "copy post data" and pasted it into an editor:

尽管我只对当前更改的字段感兴趣,但仍提交了该表单的每个字段:

every field of that form is submitted although i am only interested in the 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 a way to reduce the 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

甚至只是

includeForeignCurrencies=on

提前谢谢!

解决方法:

作为一种可能的解决方法,我提出禁用所有未触发发布的输入,并在ajax complete中重新启用它们. 发布数据的大小现在为200 B,而不是2000 B.

as a possible workaround i came up with disabling all inputs that did not trigger the post and re-enable them in ajax complete. post data size is now 200 B instead of 2000 B.

由于我不确定这是否还会导致其他问题,因此这是问题的更新,而不是答案.

as i am not sure if this may cause any other issues, this is an update of the question, not an 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:

javascript/jQuery:

function prepareAjaxPost(source){   

   //keep already 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 that has no visual effect for users

    });
}

function ajaxPostComplete(data) {
    switch (data.status) {      
        case "success": {

           $("#form-search :input.blocked").each(function(){
              $(this).attr("disabled",false).removeClass("blocked");     
           });

           break;
        }
}

推荐答案

首先阅读最后的"edit 2"

我知道您的问题是关于JSF 2.3的,但是出于好奇,我想看看在纯JSF中是否完全有可能.好处是,通过重写jsf.js函数,至少对于Mojarra 2.2.8(没有很快的其他环境)来说似乎是可能的.而且...如果您希望它是有条件的",那么不要在每个输入/按钮/...上都添加一个传递属性.

I know your question is about JSF 2.3, but out of curiosity, I wanted to see if it would be possible at all in plain JSF. And the good thing is that it seems possible for at least Mojarra 2.2.8 (did not have any other environments at hand quickly) by overriding a jsf.js function. And... if you want it to be 'conditional', so not on every input/button/..., also add a passthrough attribute.

我检查/调试了Mojarra jsf.js文件的源代码,发现只有在创建完整的查询字符串之后才可以剥离/过滤出字段,而不是使用PrimeFaces方式阻止/添加"字段.可以执行此操作的函数是getViewState,并通过覆盖此函数,调用原始函数并在返回结果之前添加一些逻辑来使一切正常.缺点是它可能会过滤掉很多内容(请参阅最后的评论)

I checked/debugged the sourcecode of the Mojarra jsf.js file and noticed it is only possible to strip/filter out fields after the full querystring is created instead of the PrimeFaces way where they prevent fields to be added 'upfront'. The function where this can be done is the getViewState and by overriding this, calling the original one and adding some logic before returning the result, it all seems to work. The downside is that it might filter out to much (see the comment at the end)

要添加到您的代码中的js(确保在之后 jsf.js之后加载)

The js to add to your code (make sure it loaded is 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 from the input (Mojarra puts attributes without camelcasing in the html, so pt:partialSubmit in the xhtml becomes partialsubmit in the html 
    var partialSubmit = eventSource.attributes['partialsubmit'];

    //If not on the input, check the 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 the 'execute' list
        var execute = this.ajax.request.arguments[2].execute;
        // TODO check for 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];
            for (i=0;i<params.length; i++) {
                var kv = params[i].split("=");
                if (kv[0] === kv[1] || //to pass on the form id value keypair. Not sure this is needed
                    kv[0] === "javax.faces.ViewState" || // check if other 'relevant' fields need to be passed on (viewid, conversationid etc... How to detect these?
                    encodeURIComponent(id) === kv[0]) {
                    kvpairs.push("&"+params[i]);
                }
            }
        }
        return kvpairs.join("");
    } else {
        return myViewState;
    }
}

下面提供用法示例.在此示例中,第一个和最后一个输入字段已将pt:partialSubmt="true"添加到输入中(添加到ajax标记后无法使其工作).还有两个启用了Ajax的h:commandButtons,一个带有部分提交,一个没有部分提交.使用浏览器开发人员工具,您可以看到使用它们之间的差异

And example of the usage is provided below. In this example the first and last input fields have pt:partialSubmt="true" added to the inputs (could not get it to work when added to the ajax tag). There are also two ajax enabled h:commandButtons, one with and one without the partial submit. Using the browser developer tool you can see the 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" to the form makes it work for every input/button in the 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 all 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 all 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>

您可以在javascript代码中看到一些需要优化的注释,但这是一个不错的开始/开始.

You can see some comments in the javascript code that it needs optimization but it is a good working start/beginning.

  • 添加了将pt:partialSubmit="true"添加到<h:form>的选项,因此可以广泛使用它
  • 通过使用OmniFaces <o:form includeRequestParams="true">研究了现有请求参数的传递,由于它们不在表单字段的"viewState"键值对中,因此它们未被剥离.
  • Added the option to add pt:partialSubmit="true" to the <h:form> So using it form wide
  • Investigated the passing on of existing request params by using the OmniFaces <o:form includeRequestParams="true"> and they are not stripped due to them not being in the 'viewState' key-value pairs of the form fields.

伟大的OmniFaces项目将在即将发布的3.0版本中提供. @BalusC已完成提交,该提交已关闭

The great OmniFaces project will have this in the upcoming 3.0 release. A commit has been made by @BalusC that closed issue 394 that I created there as a result of this question. WITHIN 5 DAYS Using the

<o:form> 

默认为partialSubmit

will default to a partialSubmit

这篇关于&lt; f:ajax render =“&quot; @ none&quot;执行="@ this"并以较大的形式减少提交的帖子数据的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆