欢迎进入Wiki » FAQ » 使用 $.formDialog 开发 AJAX 表单(含附件上传)?

使用 $.formDialog 开发 AJAX 表单(含附件上传)?

在2015-05-22 11:02上被李小翔修改
评论 (0) · 附件 (0) · 记录 · 信息

BroFramework 中集成了 JQuery UI,因此,我们通常采用其 dialog 组件来开发 AJAX 表单。

对于多数 AJAX 表单来说,基本流程如下:

  1. 创建一个 dialog,并初始化大小、按钮等属性,多数情况下,仅包含“确定”、“关闭”两个按钮
  2. 加载一个 AJAX 表单,加载完成后显示 dialog
  3. 触发确定按钮后,执行 ajax 提交并回显

如下面的两个例子所示:

/**
 * 示例1:AJAX 表单提交
 */

function createFolder(url) {
   var id = "dlgCmsCreateFolder";
   var dlg = $j("#"+id);
   if ( dlg.length == 0 ) {
        $j("<div id='"+id+"' class='body'></div>").appendTo("body");
        dlg = $j("#"+id);
        dlg.dialog({
            autoOpen:false, modal:true, title:"创建文件夹", width:420, resizable:false,
            buttons: {
               "提交": function() {
                   var fm = $j("#fmCreateFolder");
                    showProcessingDlg();
                    $j.post(fm[0].action, fm.serialize(), function(msg){
                        hideProcessingDlg();
                        showAjaxMsg(msg, function(){
                            dlg.dialog("close");
                           try { parent.reloadNode($j("#folderId")[0].value); }catch(e){}
                            location.reload();
                        })
                    })
                },
               "关闭": function() { $j(this).dialog("close"); }
            } // end of buttons
       }) // end of dlg.dialog
   }
    dlg.load( url, function(msg){
       if (/{"error"/.test(msg)) return;
        dlg.dialog('open');
        $j("#fmCreateFolder #name").focus()
    });
}

/**
 * 示例2:AJAX 附件上传
 */

function createFile(url) {
   var id = "dlgCmsCreateFile";
   var dlg = $j("#"+id);
   if ( dlg.length == 0 ) {
        $j("<div id='"+id+"' class='body'></div>").appendTo("body");
        dlg = $j("#"+id);
        dlg.dialog({
            autoOpen:false, modal:true, title:"上传附件", width:450, resizable:false,
            buttons: {
               "上传": function() {
                   if ( $j("#fmCreateFile").find(":file").val() ) {
                       if ( $j.browser.fileApiSupported ) {
                            $j("#fmCreateFile").submit();
                        } else {
                            showProcessingDlg(function(){
                                $j("#fmCreateFile").submit();
                               return false;
                            });
                            $j(this).dialog("close");
                        }
                    }
                },
               "关闭": function() { $j(this).dialog("close"); }
            } // end of buttons
       }) // end of dlg.dialog
   }
    dlg.load( url, function(msg){
       if (/{"error"/.test(msg)) return;
        dlg.dialog('open');
       // AJAX 上载,如果支持XMLHttpRequest Level 2,则显示上传进度
       $j("#fmCreateFile").ajaxForm({
            dataType: 'json',
            beforeSend : function() {
               if ( $j.browser.fileApiSupported ) {
                    dlg.closest("div.ui-dialog").find(".ui-dialog-titlebar, .ui-dialog-buttonpane, .ui-dialog-titlebar-close, .ui-resizable-handle").hide();
                    $j("#fmCreateFile").html('&nbsp;<br/><div class="progressbar"><div class="progress-label" style="float:right; margin-top:5px">Uploading...</div></div><br/>&nbsp;');
                    $j("#fmCreateFile .progressbar").progressbar({value: 0});
                }
            },
            uploadProgress: function(event, position, total, percentComplete) {
                $j("#fmCreateFile .progressbar").progressbar( "value", percentComplete );
                $j("#fmCreateFile .progress-label").text( percentComplete + '%' );
            },
            complete: function(xhr) {
               if ( $j.browser.fileApiSupported ) {
                    dlg.closest("div.ui-dialog").find(".ui-dialog-titlebar, .ui-dialog-buttonpane, .ui-dialog-titlebar-close, .ui-resizable-handle").show();
                    dlg.dialog("close");
                }
            }
        })
    });
}

上面的代码乍一看,麻烦得很,尤其是每次写AJAX表单时,总是要拷贝粘贴大量代码,因此,BroFWK提供了一个简化的API:$.formDialog,简化后的代码如下所示:

/**
 * 示例1:AJAX 表单提交
 */

function createFolder(url) {
    $j.formDialog({
        modal:true, title:"创建文件夹", width:420, resizable:false,
        id: "dlgCmsCreateFolder", url: url,
       "submit.close": true, "submit.reload": true,
       "submit.after": function() {
           try {
                parent.reloadNode($j("#folderId").val());
            } catch(e) {}
        }
    })
}

/**
 * 示例2:AJAX 附件上传
 */

function createFile(url) {
    $j.formDialog({
        modal:true, title:"上传附件", width:450, resizable:false,
        id: "dlgCmsCreateFile", url: url, cache: false,
       "submit.close": true, "submit.reload": true,
       "submit.before": function() {
           return $j("#fmCreateFile").find(":file").val();
        }
    })
}

和简化前的代码示例相比,代码量整整减少了2/3。

下面对 $.formDialog 做个简单的介绍:

  • 封装了jquery ui的dialog组件,仅接收一个 options 参数,参数中的内容除了下面的注释所写的内容外,全部和 jqui 的 dialog 兼容
  • 参数 options 说明:
    @param options.id  HTML容器的ID,如果不存在,则会创建一个DIV
    @param options.html  表单的HTML文本内容,当容器不存在、并创建容器时将本参数的值放到 DIV 中
    @param options.url  表单的URL,通过AJAX加载
    @param options.cache  是否保存表单URL的Cache,默认为true
    @param options.progressbar  如果有附件域、且浏览器支持XMLHttpRequest Level 2,是否显示上传进度条,默认为真
    @param options.'buttons.default' 是否生成默认的确定(提交)、关闭(取消)按钮,默认为 true,即如果没有按钮Ok、Close按钮,则自动生成
    @param options.'buttons.OK'  默认确定按钮的名称,默认取i18n配置 jqui.dalog.button.OK,即“确定”,如果为 false 则不显示
    @param options.'buttons.CLOSE' 默认关闭按钮的名称,默认取i18n配置 jqui.dalog.button.CLOSE,即“关闭”,如果为 false 则不显示
    @param options.'submit.ajax'  是否采用ajax的方式提交,默认为true。
             如果提交后,需要根据上传的数据渲染或者重定向到其他页面(表单的 target 属性设为 _blank),则应设为false,此时ProcessingDlg显示3秒后自动关闭。
    @param options.'submit.close' 提交成功后是否自动关闭
    @param options.'submit.reload' 提交成功后是否自动刷新当前页面
    @param options.'submit.before' 点击“确定”前的事件,接收参数 form,如果返回 false 则中断提交
    @param options.'submit.after' 点击“确定”并且ajax提交成功后的事件,接收参数 message(服务器返回的对象)
    @params options.buttons   jqui dialog 的按钮参数,用法不变,但其回调函数中可以调用 this.submit()、this.close()、this.form() 来直接提交、关闭、获取表单对象
     
  • 需要注意的是,附件上传使用的是 jqeury 插件 ajaxForm,由于浏览器的支持程度不同,因此在控制器中需要采用下面的写法来接收附件、返回结果:
    def importExcel() {
       // 解析 Excel 文件
       Map result = bropen.toolkit.utils.office.MSExcelUtils.readAll(request)
       
       // 处理数据
       if ( !result.error ) {
           ....
       }
       
       // 渲染结果
       if ( isAjax() ) {
            render(result as JSON)
       } else {
            render(text:"<textarea>${result?.encodeAsJSON()}</textarea>", contentType:"text/html", encoding:"UTF-8")
       }
    }

    控制器中,还可以通过 request.getFileMap() 来获得所有上传的附件,或者使用默认的 attachmentService.save 将附件保存到 Domain 实体中。
    此外,提交过程默认为ajax的,如果上传附件后需要渲染一个预览界面,则应该设置 ‘submit.ajax’ 参数为 false,即禁用 ajax 方式提交表单。
标签: BroFramework ajax
在2014-06-11 17:32上被李小翔创建

Copyright © 2013 北京博瑞开源软件有限公司
京ICP备12048974号