Ajax数据双向数据绑定策略?

2024-01-02

我想 1) 绘制创建表单字段并使用 javascript 对象中的数据填充它们 2) 每当表单字段的值发生变化时更新这些支持对象

第 1 点很容易。我有一些 js 模板系统,我一直在使用它们,效果非常好。

第二点可能需要一些思考。在谷歌上快速搜索“ajax 数据绑定”,发现了一些看起来基本上是单向的系统。它们旨在根据支持 js 对象更新 UI,但似乎没有解决当 UI 发生更改时如何更新这些支持对象的问题。有人可以推荐任何可以为我做这件事的图书馆吗?这是我可以自己写的东西,不会太麻烦,但如果这个问题已经被思考清楚,我宁愿不重复这项工作。

////////////////////// 编辑 /////////////////

我创建了自己的 jquery 插件来完成此任务。这里是。请告诉我它是否有用,以及您是否认为值得将其变得更加“官方”。如果您有问题或疑问,也请告诉我。

/*

    Takes a jquery object and binds its form elements with a backing javascript object. Takes two arguments: the object 
    to be bound to, and an optional "changeListener", which must implement a "changeHappened" method.

    Example: 

    // ============================
    // =     backing object       =
    // ============================

    demoBean = {
        prop1 : "val",
        prop2 : [
            {nestedObjProp:"val"},
            {nestedObjProp:"val"}
        ],
        prop3 : [
            "stringVal1",
            "stringVal12"
        ]
    }

    // ===========================
    // =        FORM FIELD       =
    // ===========================

    <input class="bindable" name="prop2[1].nestedObjProp">


    // ===========================
    // =       INVOCATION        =
    // ===========================

    $jq(".bindable").bindData( 
        demoBean, 
        {changeHappened: function(){console.log("change")}}
    )


*/


(function($){


    // returns the value of the property found at the given path
    // plus a function you can use to set that property
    var navigateObject = function(parentObj, pathArg){
        var immediateParent = parentObj;
        var path = pathArg
            .replace("[", ".")
            .replace("]", "")
            .replace("].", ".")
            .split(".");
        for(var i=0; i< (path.length-1); i++){
            var currentPathKey = path[i];
            immediateParent = immediateParent[currentPathKey];
            if(immediateParent === null){
                throw new Error("bindData plugin encountered a null value at  " + path[i] + " in path" + path);
            }
        }

        return {
            value: immediateParent[path[path.length - 1]],
            set: function(val){
                immediateParent[path[path.length - 1]] = val
            },
            deleteObj: function(){
                if($.isArray(immediateParent)){
                    immediateParent.splice(path[path.length - 1], 1);
                }else{
                    delete  immediateParent[path[path.length - 1]];
                }
            } 
        }

    }

    var isEmpty = function(str){
        return str == null || str == "";
    }

    var bindData = function(parentObj, changeListener){

        var parentObj,
            radioButtons = [];
        var changeListener;
        var settings;
        var defaultSettings = {
            // if this flag is true, you can put a label in a field,
            // like <input value="Phone Number"/>, and the value
            // won't be replaced by a blank value in the parentObj
            // Additionally, if the user clicks on the field, the field will be cleared.
            allowLabelsInfields: true 
        };

        // allow two forms: 
        // function(parentObj, changeListener)
        // and function(settings). 
        if(arguments.length == 2){
            parentObj = arguments[0];
            changeListener = arguments[1]
            settings = defaultSettings;
        }else{  
            settings = $jq.extend(defaultSettings, arguments[0]);
            parentObj = settings.parentObj;
            changeListener = settings.changeListener;
        }

        var changeHappened = function(){};
        if(typeof changeListener != "undefined"){
            if(typeof changeListener.changeHappened == "function"){
                changeHappened = changeListener.changeHappened;
            }else{
                throw new Error("A changeListener must have a method called 'changeHappened'.");
            }
        };
        this.each(function(key,val){
            var formElem = $(val);
            var tagName = formElem.attr("tagName").toLowerCase();
            var fieldType;
          if(tagName == "input"){
            fieldType = formElem.attr("type").toLowerCase();
          }else{
            fieldType = tagName;
          }


            // Use the "name" attribute as the address of the property we want to bind to.
            // Except if it's a radio button, in which case, use the "value" because "name" is the name of the group
            // This should work for arbitrarily deeply nested data. 
            var navigationResult = navigateObject(parentObj, formElem.attr(fieldType === "radio"? "value" : "name"));

            // populate the field with the data in the backing object

            switch(fieldType){

        // is it a radio button? If so, check it or not based on the 
        // boolean value of navigationResult.value
        case "radio":
          radioButtons.push(formElem);
          formElem.data("bindDataPlugin", {navigationResult: navigationResult});
          formElem.attr("checked", navigationResult.value);
          formElem.change(function(){
            // Radio buttons only seem to update when _selected_, not 
            // when deselected. So if one is clicked, update the bound
            // object for all of them. I know it's a little ugly,
            // but it works.
            $jq.each(radioButtons, function(index, button){
              var butt = $jq(button);
              butt.data("bindDataPlugin").navigationResult.set(butt.attr("checked"));
            });
            navigationResult.set(formElem.attr("checked"));           
            changeHappened();
          });
          break;

        case "text":
          // if useFieldLabel is true, it means that the field is 
          // self-labeling. For example, an email field whose 
          // default value is "Enter Email".
          var useFieldLabel = isEmpty( navigationResult.value )
                   && !isEmpty( formElem.val() )  
                   && settings.allowLabelsInfields;
          if(useFieldLabel){
           var labelText = formElem.val();
           formElem.click(function(){
             if(formElem.val() === labelText){
               formElem.val("");
             }
           })
          }else{
           formElem.attr("value", navigationResult.value);
          }
          formElem.keyup(function(){
           navigationResult.set(formElem.attr("value"));
           changeHappened();
          });

          break;

        case "select":
          var domElem = formElem.get(0);
                $jq.each(domElem.options, function(index, option){
                    if(option.value === navigationResult.value){
                        domElem.selectedIndex = index;
                    }
                });
                formElem.change(function(){
                    navigationResult.set(formElem.val());
                })
          break;

        case "textarea":
          formElem.text(navigationResult.value);
          formElem.keyup(function(){
           changeHappened();
           navigationResult.set(formElem.val());
          });
          break;
      }


        });
        return this;
    };

    bindData.navigateObject = navigateObject;

    $.fn.bindData = bindData;

})(jQuery);

有大量的库可以实现您想要的。

对于初学者,您可以使用DWR http://directwebremoting.org/dwr/index.html获得 Ajax 功能。表单字段触发的方法onChange事件应该对相应的支持对象进行 DWR 调用

希望这可以帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Ajax数据双向数据绑定策略? 的相关文章

  • JavaScript 支持逐字字符串吗?

    在 C 中 您可以像这样使用逐字字符串 server share file txt JavaScript中有类似的东西吗 模板字符串支持换行 so you can do this if you want https developer mo
  • 节点遗留 url.parse 已弃用,用什么代替?

    require url parse someurl com page 已被仅弃用 并且我们严格的 linter 对此不满意 我尝试用互联网建议的内容替换我们的代码中的它new URL someurl com page 在大多数情况下都有效
  • 为什么绑定到 IEnumerable 的 ListBox 不更新?

    我有以下 XAML
  • Typescript:匿名函数内可能未定义的变量

    太长了 在匿名函数中使用变量之前检查变量仍然 TS 警告变量可能未定义 在下面的代码示例中变量baseDirId检查是否未定义 然后传递给 array map 函数 但 TS 发出警告baseDirId可以是未定义的 Typescript
  • Pug 从模板内的另一个文件调用 js 函数

    我花了将近四个小时都无法解决这个问题 而且我找不到任何针对此类问题的有用文档 这就是问题 我正在使用 pug jade 模板 我想调用 pug 模板内的函数来转换一些数据 这是主要模板 main template section each
  • 无需重定向的 HTML 页面提交

    有没有什么方法可以在不使用ajax的情况下提交html表单而无需从当前页面重定向 你可以设置一个target 为您form 这样您就可以将表单提交到新选项卡 target blank 或一个小的 隐藏的iframe target nameo
  • 仅从功能区打开一个对话框

    我有一个带有登录按钮的功能区 可打开登录对话框 我想将对话框的数量限制为一个 我正在使用函数 displayDialogAsync startAddress options callback https learn microsoft co
  • 为某个时刻添加持续时间 (moment.js)

    时刻版本 2 0 0 阅读文档后 http momentjs com docs manipulating add 我认为这很简单 Chrome 控制台 var timestring1 2013 05 09T00 00 00Z var tim
  • 为什么这个递归函数返回未定义?

    我正在尝试编写一个使用递归组合两个字符串的函数 我的代码如下 但我不知道为什么该函数返回未定义 特别是当我在基本情况下使用 console log 时 它不会打印未定义而是打印正确的值 var str3 function merge str
  • NodeJS - 将相对路径转换为绝对路径

    In my 文件系统我的工作目录在这里 C temp a b c d 在 b bb 下有文件 tmp txt C temp a b bb tmp txt 如果我想从工作目录转到该文件 我将使用以下路径 bb tmp txt 如果该文件不存在
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • 如何让php页面从html页面接收ajax post

    我有一个非常简单的表单 其中有一个名字输入字段 我捕获了表单数据 并使用标准 jQuery 发布方法通过 ajax 将其传输到 PHP 页面 但是 我根本无法从 PHP 页面获得任何在服务器端捕获数据的响应 我不确定我做错了什么或缺少什么
  • JavaScript setTimeout 和更改系统时间会导致问题

    我注意到如果我设置setTimeout未来1分钟 然后将我的系统时间更改为过去5分钟 setTimeout功能将在 6 分钟后触发 我这样做是因为我想看看夏令时系统时钟更改期间会发生什么 我的 JavaScript 网页使用setTimeo
  • 如何禁用网页中的萤火虫?

    如何使用 Javascript 禁用 firebug 我想这样做是为了向访问者隐藏我的网页的运作方式 有什么选择可以做到这一点吗 你不能 你能做的最好的事情就是混淆你的 JavaScript 实际上刮掉了 您能做的最好的事情就是将所有安全关
  • 如何捕获文本区域上的 Enter 按键而不是 Shift+Enter? [复制]

    这个问题在这里已经有答案了 I m doing it for texarea A function should be called when the user press Enter but nothing should be done
  • Firebase 身份验证和实时应用程序数据库如何保护自身安全?

    从一般开发的角度来看 我很好奇如何保护在线资源的访问 我们使用以下 Firebase 配置参数初始化 Web 应用程序 apikey authdomain projectid databaseurl messagesenderid 服务器如
  • jQuery:向左滑动和向右滑动

    我见过slideUp and slideDown在 jQuery 中 左右滑动的功能 方式怎么样 您可以使用 jQuery UI 中的附加效果来做到这一点 详情请参阅此处 http docs jquery com UI Effects Sl
  • 如何计算一行中Flexbox项目的数量?

    网格是使用 CSS flexbox 实现的 Example http jsbin com jumosicasi edit html css js output 本示例中的行数为 4 因为我出于演示目的固定了容器宽度 但是 实际上 它可以根据
  • 如何得知客户端从服务器的下载速度?

    根据客户的下载速度 我想以低质量或高质量显示视频 任何 Javascript 或 C 解决方案都是可以接受的 Thanks 没有任何办法可以确定 您只能测量向客户端发送数据的速度 如果没有来自客户端的任何类型的输入来表明其获取信息的速度 您
  • 从json中获取所有子节点

    我有以下 json var source k 01 k 02 children k 05 k 06 children k ABC k PQR k 07 k 03 我希望能够指定 k 的值并取回所有孩子 以及孙

随机推荐

  • MVC 中的 CMS 路由

    我正在 php 中创建自己的 MVC 框架 作为学习更高级编程的一种手段 我已经启动并运行了框架 但是我对当前的路由方法有一个问题 我希望该框架支持后端 cms 以补充前端网站 问题是我的路由结构的工作方式如下 mywebsite com
  • 匿名类型中的特殊字符

    我想创建一个变量名称中带有特殊字符的匿名类型 例如我有这个 new status Active 我想要类似的东西 new status Active exists true 这最终会序列化为 JSON 所以我知道我可以使用 JObject
  • 如何使用 SXSSF 写入现有文件?

    我有一个 xlsx 文件 其中包含多个包含不同数据的工作表 所有sheet中一张sheet需要容纳近10万行数据 数据需要使用java配合poi编写 这对于 SXSSFWorkbook 来说似乎非常快速和简单 我只能在内存中保留 100 行
  • where 子句中的多个“in”语句需要相互匹配

    我有一个很长的查询 本质上是以下查询的扩展 update property lease period set scca uplift 110 scca notes code 21006 where suite id CCBG08 and l
  • Laravel 服务提供者和服务容器

    在 Laravel 中访问查询 我们使用DB facades DB select 来自阿兰斯托姆网站http alanstorm com binding objects as laravel services http alanstorm
  • 从日志文件中提取特定行的数据

    我希望从长日志文件中的表中提取并打印特定行 它看起来像这样 XSCALE VERSION July 4 2012 4 Jun 2013 Author Wolfgang Kabsch Copy licensed until 30 Jun 20
  • Leaflet.js:WMS 图层样式

    我有一个 Leaflet javascript Web 应用程序 它使用 WMS 来调用 GeoServer 返回的对象是Geometry加上属性 虽然几何图形 多边形 可以像美国的县一样渲染良好 但我需要根据县人口使县图层显示不同的颜色
  • 使用具有严格内容安全策略的 Angular Material

    我正在使用 Angular 6 和 Angular Material 6 开发企业应用程序 现在我必须为一个具有非常严格的 CSP 的新客户构建项目 那就是 内容安全策略 default src self 该政策无法修改 我搜索了以前的答案
  • 异步/等待 Lambda

    我有一个奇怪的问题 结合 async await 使其工作 我创建了一个小程序 它基本上应该处理每个操作的 try catch internal static void HandledAction Action action Info in
  • 将 arrayList 数据加载到 JTable 中

    我正在尝试通过名为的方法设置项目FootballClub到目前为止还好 但后来我从中创建了一个 arrayList 但不知何故找不到一种方法将此信息存储到 JTable 中 问题是我找不到设置固定行数的方法 这是我的代码 起始联赛类别 im
  • 如何使用 Django Usurena“mugshot”模板变量

    我正在尝试在 Django 网站中使用 Userena 但我似乎不知道如何使用模板标签来显示照片 我尝试了以下方法来输出图像标签中的 URL img src and img src 有人有一些见解吗 Thanks 基于 alican 的答案
  • 如何使用 openssl 创建包含 CRL 分发点的证书?

    我在使用 openssl 创建包含用于测试的 crl 分发点的 x509 证书时遇到问题 我检查了文档并找到了用于此目的的配置设置 crlDistributionPoints 不幸的是 openssl 始终生成 x509 版本 1 证书 而
  • 使用 ColdFusion 从 SQL 数据库抓取长文本,输出被截断

    我有一个 SQL 数据库ntext保存页面内容的字段 我正在使用 ColdFusion 查询信息并将其传递到表单中 该表格使用ckeditor来处理这个特定的字段 该字段目前包含大约4000个字符 在 ckeditor 窗口中查看时 似乎缺
  • 1l 表示长整型,1f 表示浮点型,1d 表示双精度型,那么字节呢?

    1l 表示长整型 1f 表示浮点型 1d 表示双精度型 那么字节呢 long l 1l float f 1f double d 1d byte b 1 相当于什么byte 它存在吗 不 没有后缀可以附加到数字文字上以使其成为byte See
  • 不透明内容到底意味着什么?

    Here http docs oracle com javase 7 docs api java nio file attribute BasicFileAttributes html isRegularFile 28 29我们有描述isR
  • PHP-PDO 获取以列作为索引、以列作为值的结果集[重复]

    这个问题在这里已经有答案了 您好 我有一个具有以下结构的表 date price 2014 02 19 34 2014 02 20 30 2014 02 21 28 目前 PDO FETCH ASSOC 返回一个格式如下的关联数组 arra
  • 如何在Android中每2个字符后连接特殊符号作为冒号

    我想连接或附加特殊字符作为冒号 String 中每 2 个字符之后 例如 原始字符串如下 String abc AABBCCDDEEFF 连接或附加冒号后如下 String abc AA BB CC DD EE FF 所以我的问题是我们如何
  • preg_replace、str_replace 和 substr_replace 在特殊条件下不起作用

    我有以下代码 这段代码找到字符串中的所有 html 标签 并将它们替换为 0 1 2 等 至少这是有意的 但不起作用 str some text a href review review a here a class abc href ab
  • 无法使用 ID 在服务器上进行更新

    我正在更新表单 并且想使用 id 在服务器上发出更新请求 我的模型是 var CampaignEditModel Backbone Model extend urlRoot http localhost 3033 campaign upda
  • Ajax数据双向数据绑定策略?

    我想 1 绘制创建表单字段并使用 javascript 对象中的数据填充它们 2 每当表单字段的值发生变化时更新这些支持对象 第 1 点很容易 我有一些 js 模板系统 我一直在使用它们 效果非常好 第二点可能需要一些思考 在谷歌上快速搜索