jquery表格動態增刪改及取數據綁定數據完整方案


一 前言

  上一篇 Jquery遮罩插件,想罩哪就罩哪! 結尾的預告終於來了。

  近期參與了一個針對內部員工個人信息收集的系統,其中有一個需求是在填寫各個相關信息時,需要能動態的增加行當時公司有自己的解決方案 那就是用GridView 那個龐大的服務器控件,我一真就不怎么喜歡用服務器控件,於是極力說服PM用js來處理,並成功爭取到了,先說下如果用GridView來處理的缺點,

1 生成的html代碼會比較冗余,

2 每一個操作都會伴隨頁面回發,

3 每個操作都會刷新頁面,這樣的用戶體驗極差,就算用updatepanel也還是會有回發,

4 有點殺雞用牛刀的感覺

那用js來處理以上的問題就都不存在了,重點是還能把js鞏固一下(算是私心吧),由於項目的時間非常緊,而且又轉成用js處理又沒有相關的經驗,整個過程壓力還是很大的,免不了加班,但是做自己喜歡的事,就算加班我也是樂在其中

 

二 插件介紹

 

基本需求如下:

1 可以動態增加 刪除行,

2 可以對行內數據進行校驗,並支持自定義校驗提示信息

3 能取到表格中的數據

4 能綁定后台數據到表格中

當然這只是大概的需求,還有很多小的細節就不寫了,也不是本文的重點。下面詳細寫下每個功能的具體思路,當然我的肯定不是最好的思路,代碼也肯定可再優化。

前后端數據交互過程如下:

前---后 

         前端取數據--->隱藏域---->后端取隱藏域值解析並存DB

后---前

        后端取數據---->隱藏域----> 前端取隱藏域值添加到表格中

 

先看下效果 

 

 

 

2.1  增加行 刪除行

     增加行

     思路: 跳過第一行(也就是表頭),復制第二行的html元素追加到表中,(在IE8中好像會將復制的行內文本值也會被追加到新的行中,這時需要遍歷新的行將其清空)

     代碼如下

    //增加行
    $.fn.tables.addRow = function (gridId) {
        var tbRow = $("#" + gridId).find("tr").eq(1).html();
        var num = $("#" + gridId + " tr").length;
        $("#" + gridId).append("<tr id=" + num + ">" + tbRow + "</tr>");
        $("#" + gridId).find("tr").last().find("td").last().children().removeAttr("name").attr("value", "");
    };

 

  

     刪除行:

     思路:點刪除時通過當前元素找到其父元素"tr"然后再刪除該"tr"元素

     代碼:

    //刪除行 
    //參數obj  當前對象
    $.fn.tables.deleteRow = function (obj) {
        var $this = $(obj);
        if ($this.parents("table").find("tr").length <= 2) {
            return false;
        }
        $this.parents("tr").remove();
    };

 

  2.2 取表格內數據: 

  思路:為了讓前端的數據到后端容易解析,決定用json格式,將實體的屬性名添加到元素的name屬性中,組成結果時用元素的name屬性做名稱,value屬性做值

遍歷表格中每一行,並添加到一個數組中。取到的結果格式就是這樣的 {"Relation":"Zery","RelativesName":"Zhang"},傳到后台時將其序列化成對象就可以了

   

 <input name="RelativesName" type="text" style="width: 100px" class="required" />

 

代碼:

   //取表格所有數據
    //返回值為一個數組,數組內每一個元素對應一行內的數據;
    $.fn.tables.getResult = function (gridId) {

        var resultArray = new Array();
        $("#" + gridId).find("tr").slice(1).each(function () {

            var trResult = "{";

            $(this).find("td").each(function () {
                var $child = $(this).children();

                if ($child.length > 1) {
                    //td下有多個元素的(多個元素會用"|"拼接起來)
                    //td下有多個元素的暫時禁用
                    //$child.each(function () {
                    //    //alert($(this).attr("type"));
                    //    switch ($(this).attr("type")) {
                    //        case "text":
                    //            //alert($child.val() + "文件框的!");

                    //             trResult += '"' + $(this).attr("name") + '"' + ":" + '"' + $(this).val() + '"' + ",";
                    //            break;
                    //        case "select":
                    //            // alert($(this).find("option:selected").text());

                    //            trResult += '"' + $(this).attr("name") + '"' + ":" + '"' + $(this).find("option:selected").val() + '"' + ",";
                    //            break;
                    //        case "checkbox":

                    //            if ($(this).attr("checked") === "checked") {

                    //                trResult += '"' + $(this).attr("name") + '"' + ":" + '"' + $(this).val() + '"' + ",";
                    //            }
                    //            break;

                    //        case "radio":
                    //            if ($(this).attr("checked") === "checked") {

                    //                trResult += '"' + $(this).attr("propertys") + '"' + ":" + '"' + $(this).val() + '"' + ",";
                    //            }
                    //            break;

                    //        default:
                    //    }

                    //});
                    // trResult.push(valueStr);

                } else {
                    //td 下只有一個元素
                    switch ($child.attr("type")) {
                        case "text":

                            trResult += '"' + $child.attr("name") + '"' + ":" + '"' + $child.val() + '"' + ",";
                            break;
                        case "select":

                            trResult += '"' + $child.attr("name") + '"' + ":" + '"' + $child.find("option:selected").val() + '"' + ",";
                            break;
                        case "checkbox":
                            if ($(this).attr("checked") === "checked") {
                                trResult += '"' + $child.attr("name") + '"' + ":" + '"' + $child.val() + '"' + ",";
                            } else {
                                trResult += '"' + $child.attr("name") + '"' + ":0" + '"' + ",";
                            }
                            break;
                        case "radio":
                            if ($(this).attr("checked") === "checked") {
                                trResult += '"' + $child.attr("propertys") + '"' + ":" + '"' + $child.val() + '"' + ",";
                            } else {
                                trResult += '"' + $child.attr("propertys") + '"' + ":0" + '"' + ",";
                            }
                            break;


                        default:
                    }
                }
            });

            trResult = trResult.substring(0, trResult.length - 1);
            resultArray.push(trResult + "}");

        });

        return resultArray;
    };
View Code

 

2.3 驗證行數據:

思路:遍歷每行中的元素根據元素類型來做判空處理,如果為空則在元素后追加提示信息,如果元素需要自定義錯誤信息時可以給元素加一個errormsg屬性 

代碼:

  //驗證行
    $.fn.tables.validateRow = function (gridId) {

        //是否驗證通過
        var isPass = true;

        $("#" + gridId).find("tr").slice(1).each(function () {

            $(this).find("td").each(function () {
                if ($(this).children().hasClass('text-error'))
                {
                    return isPass = false;
                }

                var $this = $(this).children();

                if ($this.length > 1) {
                    //checkbox選中數
                    if ($(this).find("input[type='checkbox']").length > 0) {
                        var checkedNum = $(this).find("input[type='checkbox'][checked]").length;
                        if (checkedNum <= 0) {
                            //TODO:復選框應該默認有選中項目不需要做驗證
                            // message = "此字段必填";
                            //return message;
                        }
                    }
                    //radio選中數
                    if ($(this).find("input[type='radio']").length > 0) {
                        var radioNum = $(this).find("input[type='radio'][checked]").length;
                        if (radioNum <= 0) {
                            //TODO:復選框應該默認有選中項目不需要做驗證
                            //message = "此字段必填";
                            //return message;
                        }
                    }
                } else {
                   
                    switch ($this.attr("type")) {
                        case "text":
                            var errorMsg = "此字段為必填項!";
                            if ($this.hasClass("required")) {
                                if ($.trim($this.val()) == "") {

                                    isPass = false;
                                   
                                    if ($this.attr("errormsg") == undefined) {

                                        $this.addClass('error').after("<span class='help-block text-error'>" + errorMsg + "</span>");
                                    } else {
                                        errorMsg = $this.attr("errormsg");
                                        $this.addClass('error').after("<span class='help-block text-error'>" + errorMsg + "</span>");
                                    }
                                }
                            }
                            if ($this.hasClass("detepickers")) {
                                if ($.trim($this.val()) == "") {
                                    isPass = false;
                                    $this.addClass('error').after("<span class='help-block text-error'>" + errorMsg + "</span>");
                                }
                            }
                            break;
                        case "select":
                            //默認有選中項不需要做驗證
                            //若選中項為“請選擇”時可以根據選中值來驗證
                            break;
                        default:
                    }
                }
            });

        });
        return isPass;

    };
View Code

 

2.4 綁定數據

思路: 后台取到值后序列化成json后通過隱藏域傳到前端,前端根據元素的name屬性值與 Json串中的的key 做對比如果相等則賦值, 需要注意的是 所有的元素我都是用type屬性來區分的 如果該元素沒有type屬性則需要自己加上 如 select 元素 需要加上 type='select'  

代碼:

    //綁定數據
    $.fn.tables.bindData = function (gridId, tbResult) {

        //返回結果為一個數組
        // var result = $("#<%=hd"+gridId+".ClientID %>").val();
        var jsons = $.parseJSON(tbResult);
        if (jsons == null) {
            return;
        }
        var trHtml = $("#" + gridId).find("tr").slice(1).first().html();

        //遍歷行結果
        for (var i = 0; i < jsons.length; i++) {
            var trnum = $("#" + gridId).find("tr").slice(1).length - 1;
            if (i > trnum) {
                $("#" + gridId).append("<tr>" + trHtml + "</tr>");

            }

            //遍歷行中每一列的key 
            for (var key in jsons[i]) {

                $("#" + gridId).find("tr").eq(i + 1).find("td").each(function () {
                    var $child = $(this).children();

                    if ($child.attr("name") === key || $child.attr("propertys") === key) {

                        switch ($child.attr("type")) {
                            case "text":
                                $child.val(jsons[i][key]);
                                break;
                            case "select":
                                //可以根據value 來設置選中項目
                                $child.find("option").each(function () {
                                    var value = $(this).val();
                                    if (value === jsons[i][key]) {
                                        $(this).attr("selected", true);
                                    }
                                });

                                break;
                            case "checkbox":
                                //可以根據value 來設置選中項目

                                $child.each(function () {
                                    var name = $(this).attr("name");
                                    if (name === key && $(this).val() === jsons[i][key]) {
                                        $(this).attr("checked", true);
                                    }
                                });

                            case "radio":
                                $child.each(function () {
                                    var name = $(this).attr("propertys");
                                    if (name === key && $(this).val() === jsons[i][key]) {
                                        $(this).attr("checked", true);
                                    }
                                });
                                break;
                            case "a":
                            case "button":
                                $child.attr("value", jsons[i][key]);
                                break;
                            default:
                        }
                    }
                });

            }

        }
    };
View Code

 

以上都只是簡單介紹思路,雖然寫出來只有一點點,但是 當時在開發時在某些點卻時想了很久,因為針對項目做了很多的特殊修改,所以這里只實現很基本的功能,代碼也僅供參考,主要還是實現的思路

 

三  總結

   項目在幾天前已經上線了,用戶的反應還不錯,也算對得起自己的付出吧,當時承擔着項目延期的風險,決定用js來做的理由很簡單,只是想把用戶體驗做的好一點。

做完后想想,有時候我們應該對自己要求高一點,不要總活在自己的舒適區,有挑戰才能有成長。

 

源碼示例下載:http://files.cnblogs.com/zery/WebApplication1.rar

 

 

如果您覺得本文有給您帶來一點收獲,不妨點個推薦,為我的付出支持一下,謝謝~

如果希望在技術的道路上能有更多的朋友,那就關注下我吧,讓我們一起在技術的路上奔跑


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM