Pass parameters to server using hidden field

Infrastructure: freemarker + webwork + sitemesh + Jetty + Selenium  + Junit

We use the basic html control of <select> in the page, which list down all the product types, and it dynamically load all the product types according to the product family user inputs, we do this using the Ajax, so every time user confirm his changes, an separate async XMLHttpRequest request would be sent to server using Javascript.

function loadDynamicProductTypes(){
    if(event.keyCode == 13){
        var familyName = document.getElementById("productFamily").value;
        var xmlhttp;
        if (window.XMLHttpRequest)
        {// code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp=new XMLHttpRequest();
        }
        else
        {// code for IE6, IE5
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }
        xmlhttp.onreadystatechange=function()
        {
            if (xmlhttp.readyState==4 && xmlhttp.status==200)
            {
                document.getElementById("hiddenAjaxResponse").innerHTML = xmlhttp.responseText;
                var doc = document.getElementById("hiddenAjaxResponse").document;
                document.getElementById("productTypes").options.length = 0;
                for(var i = 0; i < doc.getElementById("dynamicProductTypes").options.length; i++){
                    document.getElementById("productTypes").options.add(new Option(doc.getElementById("dynamicProductTypes").options[i].value, doc.getElementById("dynamicProductTypes").options[i].value));
                }
            }
        };
        xmlhttp.open("GET","/report/GetDynamicProductTypes.action?productFamily="+familyName,true);
        xmlhttp.send();
        event.cancelBubble = true
    }
}


The in order to handle the Ajax response more easily, we put a hidden field in the result page.

<div id="hiddenAjaxResponse" style="display:none"></div>

then we can use document.getElementById("productTypes").options and so on to manipulate these controls in the Ajax response.


After receiving the request from client, GetDynamicProductTypes.action would handle the request and returns the list of dynamic product types.

GetDynamicProductTypesAction.java

public class GetDynamicProductTypesAction extends MyBaseAction{

    private ProductServiceProxyImpl productServiceProxy;
    public List<String> getProductTypes() {
        return productTypes;
    }

    private List<String> productTypes = new ArrayList<String>();

    @Override
    protected String doExecute() throws Exception {
        pzTypes = getDynamicProductTypes();
        return SUCCESS;
    }

    public List<String> getDynamicProductTypes() throws SubscriptionServiceException, RemoteException {
        //logic to get the product types dynamically.
        return productTypes;
    }
}

After handing of the above action, it returns "success", then the response would be rendered using the configured page in xwork.xml.


dynamicProductTypes.ftl

[#ftl]
[@setTypesOptions/]

[#macro setTypesOptions]
<select id="dynamicProductTypes" name="dynamicProductTypes" multiple="true" height="40" size="10" width="50">
    [#assign productType = "" /]
    [#foreach productType in productTypes]
        <option value="${productType}">${productType}</option>
    [/#foreach]
</select>
[/#macro]


xwork.xml

    <package name="report" extends="default" namespace="/report">
        <action name="ViewReport" class="web.action.report.ViewReportAction">
            <result name="input" type="freemarker">/pages/report/searchProducts.ftl</result>
            <result name="success" type="freemarker">/pages/report/searchProducts.ftl</result>
        </action>
        <action name="GetDynamicProductTypes" class="web.action.report.GetDynamicProductTypesAction">
            <result name="success" type="freemarker">/pages/report/dynamicProductTypes.ftl</result>
        </action>
    </package>

1. After getting the product types, user does multi select, press "search", then the final product result list is displayed in the page, sine we need to sort the result list, how to pass the parameters to server regarding the sort column and sort direction?

Html tag in ftl page:

 <th οnclick="sortProductListOn('key', 'searchProductParamsForm');" nowrap="nowrap" style="text-align:center;">[@sortDirectionImage "key"/]Key</th>

Freemarker macro:

[#macro sortDirectionImage column]
    [#if (fields.sortColumn == column)]
        [#if (fields.sortDirection == "Up")]
        <img src="../images/icons/bullet_arrow_up.gif" alt="Up"/>
        [#else]
        <img src="../images/icons/bullet_arrow_down.gif" alt="Down"/>
        [/#if]
    [/#if]
[/#macro]

JS:

function sortProductListOn(columnName, formId) {
    if (document.getElementById("sortColumn").value == columnName) {
        document.getElementById("sortDirection").value = (document.getElementById("sortDirection").value == "Up" ? "Down" : "Up");
    }
    document.getElementById("sortColumn").value = columnName;
    checkProductTypes();
    document.getElementById("isSorting").value = "true";
    document.getElementById(formId).submit();
}

function checkProductTypes(){
    for(var i = 0; i < document.getElementById("productTypes").options.length; i++){
        document.getElementById("hiddenProductTypes").options.add(new Option(document.getElementById("pzTypes").options[i].value, document.getElementById("productTypes").options[i].value));
        document.getElementById("hiddenProductTypes").options[i].selected = true;
    }
}

1) After submitting the form using the Javascript, the corresponding action would handle this request in server side, it will try to get the data from cache in the session(SessionAware), if no result, then it gets the data from db directly, but it may take a while.

    public String doDefault(){
        return INPUT;
    }

    @Override
    protected String doExecute() throws Exception {
        String key = getSatisfyingProductsCacheKey();
        boolean isSorting = Boolean.parseBoolean(stringValueForField("isSorting"));

        if(isSorting && session.containsKey(key)){
            resultList= sortExpirationProducts((List<SatisfiedProduct>)session.get(key));
        }
        else{
            resultList= sortExpirationParameters(//get from db//)
            updateCache(key, resultList);
        }

        return SUCCESS;
    }

a. When user first open the web in browser, the web app should show the default page, without any action executed in server side, you can do this by configuring this as below, so server would execute the doDefault() method, but the method actually does nothing but returns "success", so actually essentially it just redirects the user to input page as configured above in xwork.xml

    <package name="default" extends="webwork-default">        
        <action name="Home" class="web.action.NoOpAction">
            <result name="success" type="redirect">/security/ViewProductsInfo!default.action</result>
        </action>
    </package>

b. As you can see, how could server tell if the user is sorting or just trying a brand new search to load directly from db?

there is a hidden filed in client page which would be set with the proper value("true", "false") before submitting the form, so server would know if user is doing sorting or not.

(normally if user click the 'search" button, then he is trying to do a new search, then program need to load all the data from db, instead, if user is clicking on the sorting icon, then program just need to get the data from cache, sort it again and then returns it to client page for rendering).


c. "Get" and "post" are the two common methods to communicate with server, normally if you are querying data, like some kind of search form, you can use the "Get' method, then all the parameters are passed in the URL, you can easily know what you are searching for, and for others.

on the contrast, you are doing some data updating, then maybe you need to submit a bunch of data, so that server knows what you are trying to update, this way, we user the "Post" method.

No matter "Get" or "Post", all the states values of the controls inside the form would be passed to server, and actually you can get them all in the "query string", in URL, there is no such parameters appended, it appears as if no parameters are passed in the URL, but actually it is not, you can still get these parameters in the URL, then it's obvious that you can edit the URL to whatever you like and use it as a command or interface to external applications.

After the response from the server, the browser will interpret the DOM tree and generate the HTML tags on client side, this is also stored in the memory of the browser, it's static data, your real time change in the DOM tree would not be reflected in this piece of data. So after your real time, you would be the discrepancy between the browser HTML tags and in memory DOM tree.

To pass the data using the hidden filed: Since all the states values of controls in the form will be submitted to server, then you just need to dynamically change the value(other attributes also fine) before submitting to server, then server side would get the parameters by retrieving the data from corresponding hidden fields.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值