使用 dojo.xhrGet 更新表单字段会导致 dijit.checkbox 变为只读

发布于 2024-10-17 21:08:53 字数 2140 浏览 3 评论 0原文

我有一个带有表格的表单,其中有两个输入框、一个选择框和一些复选框。所有表单字段都使用 dojoType="dijit.form.{theFieldType}"。

当用户单击添加按钮时,将从 jsp 文件加载具有相同字段的新表。这是我的 ajax 函数:

    <script language="javascript">
    dojo.addOnLoad(passNumber);

    function passNumber() {
        var count = 0;
        dojo.query('#add').onclick(function() {
            var dNode = dojo.byId('more');
            count++;
            dojo.xhrGet({url: 'add.html', 
                         handleAs: "text", 
                         preventCache: true,
                         content:{fieldId:count} ,
                    load: function(data) {
                        dNode.innerHTML += data;
                        dojo.parser.parse(dNode);
                    },
                    error: function(error) {
                        dNode.innerHTML += "AJAX error: " + error;
                    }
            });
        });
    }

</script>

当单击添加按钮时,一切都会正常工作。

当您多次单击“添加”按钮时,就会出现问题。多次单击时,表中的字段会正确添加到表单中,但所有 dojoType 字段现在都是只读的(最新添加的表除外)。

今天早上我搜索了几个小时,但找不到正确的解决方案。我看到一些人发布了有关销毁对象的帖子,而另一些人则谈论了仅解析最新的字段。我尝试了几种技术但无法使其发挥作用。

我有一个简单的解决方法,可以帮助处于相同位置的人。

<script language="javascript">
    dojo.addOnLoad(passNumber);

    function passNumber() {
        var count = 0;
        dojo.query('#add').onclick(function() {
            var dNode = dojo.byId('more'+count);
            count++;
            dojo.xhrGet({url: 'add.html', 
                         handleAs: "text", 
                         preventCache: true,
                         content:{fieldId:count} ,
                    load: function(data) {
                        dNode.innerHTML = data;
                        dojo.parser.parse(dNode);
                    },
                    error: function(error) {
                        dNode.innerHTML += "AJAX error: " + error;
                    }
            });
        });
    }

</script>

主要区别是 dNode.innerHTML 中的 += 现在只是 =。我也只解析最新的 div 元素。在我的 jsp 上,我添加了一个名为“more”的空 div 容器 + 传递的数字。

我是道场新手,因此可能有一个简单的解释或解决我原来的问题。但我想向遇到同样问题的人分享我的解决方案。

谢谢

I have a form with a table that has two input boxes, a select box, and a few checkboxes. All form fields use dojoType="dijit.form.{theFieldType}".

When the user clicks the add button a new table with the same fields is loaded from a jsp file. This is my ajax function:

    <script language="javascript">
    dojo.addOnLoad(passNumber);

    function passNumber() {
        var count = 0;
        dojo.query('#add').onclick(function() {
            var dNode = dojo.byId('more');
            count++;
            dojo.xhrGet({url: 'add.html', 
                         handleAs: "text", 
                         preventCache: true,
                         content:{fieldId:count} ,
                    load: function(data) {
                        dNode.innerHTML += data;
                        dojo.parser.parse(dNode);
                    },
                    error: function(error) {
                        dNode.innerHTML += "AJAX error: " + error;
                    }
            });
        });
    }

</script>

When clicking the add button everything works like it should.

The problem arises when you click the add button more than once. On multiple clicks the fields in the table get added to the form correctly but all the dojoType fields are now read-only (except the newest added table).

I searched for a few hours this morning and could not find the correct fix for this. I saw some people posted about destroying the objects while other talked about only parsing the newest fields. I tried several techniques and could not get it to work.

I have a simple work around that might help someone in the same position.

<script language="javascript">
    dojo.addOnLoad(passNumber);

    function passNumber() {
        var count = 0;
        dojo.query('#add').onclick(function() {
            var dNode = dojo.byId('more'+count);
            count++;
            dojo.xhrGet({url: 'add.html', 
                         handleAs: "text", 
                         preventCache: true,
                         content:{fieldId:count} ,
                    load: function(data) {
                        dNode.innerHTML = data;
                        dojo.parser.parse(dNode);
                    },
                    error: function(error) {
                        dNode.innerHTML += "AJAX error: " + error;
                    }
            });
        });
    }

</script>

The main difference is the += in the dNode.innerHTML is now an = only. Also I only parse the newest div element. On my jsp I added an empty div container called 'more' + the number passed.

I am new to dojo so there might be an easy explanation or fix for my original problem. But I wanted to share my fix for anyone running into the same issue.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

口干舌燥 2024-10-24 21:08:53

您至少有一个,也可能有两个问题。

首先,您应该使用 dojo.place 将 HTML 片段放置在页面中,而不是 innerHTML

其次(你可能不会这样做)你不应该在已经运行过解析器的 DOM 部分上运行解析器。如果这样做,您最终会收到错误“尝试使用 if 'foo' 注册小部件,但该 id 已注册”。

基本上,就像 DOM 节点的 ID 必须是唯一的一样,它们对于小部件也必须是唯一的。

您有几个选择:

  1. 不要从 JSP 返回文档片段/HTML 文本。相反,请使用 JSON 或类似内容,并在 load() 回调中以编程方式构造新的表单元素。

  2. 做你正在做的事情(但确保你有唯一的ID),但不要使用innerHTML,而是使用dojo.place()。然后跟踪您正在创建的新表节点并仅对其进行解析。

例如:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html dir="ltr">

    <head>
        <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css">
    </head>

    <body class="claro ">
        <div id="container">
            <table id="original">
                <tr>
                    <td>
                        <input type="text" name="first" id="first" value="testing testing" dojoType="dijit.form.TextBox" trim="true" propercase="true">
                    </td><td>
                        <input type="text" name="second" id="second" value="testing testing" dojoType="dijit.form.TextBox" trim="true" propercase="true">
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <select dojoType="dijit.form.FilteringSelect" id="third" name="third">
                            <option value="AP">
                                Apples
                            </option>
                            <option value="OR" selected>
                                Oranges
                            </option>
                            <option value="PE">
                                Pears
                            </option>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td>
                        <input id="fourth" name="fourth" dojoType="dijit.form.CheckBox" value="agreed" checked>
                        <label for="mycheck">
                            I agree
                        </label>
                    </td>
                </tr>
            </table>
        </div>
        <div>
          <button dojoType="dijit.form.Button" type="button">
              Add new fields using HTML
              <script type="dojo/method" event="onClick" args="evt">
                  dojo.xhrGet({
                      url: '_data/mockBackendForXhrBuildDomExample.php',
                      handleAs: 'text',
                      preventCache: true,
                      load: function(data) {
                          // This is a little contrived, but hopefully you get the idea
                          console.log(data);
                          var container = dojo.byId('container');
                          var newTable = dojo.place(data, container, 'last');
                          dojo.parser.parse(newTable);                          
                      },
                      error: function(error) {
                          console.error(error);
                      }
                  });
              </script>
          </button>
        </div>
    </body>

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"
    djConfig="parseOnLoad: true">
    </script>
    <script type="text/javascript">
        dojo.require("dijit.form.FilteringSelect");
        dojo.require("dijit.form.TextBox");
        dojo.require("dijit.form.CheckBox");
        dojo.require("dijit.form.Button");
        dojo.addOnLoad(function() {


        });
    </script>

</html>

我在 http://telliott.net/dojoExamples/ 添加了此工作的示例dojo-xhrBuildDomExample.html。 AJAX 调用返回的 HTML 可以在 http://telliott.net/dojoExamples/_data/ 中找到mockBackendForXhrBuildDomExample.php(它使用 PHP time() 函数,因此每秒点击按钮的次数不要超过一次!)。

HTH,

汤姆

You have at least one, and possibly two, problems.

Firstly, you should use dojo.place to place the HTML fragment in the page, not innerHTML.

Secondly (and you may not be doing this) you shouldn't ever run the parser over a part of the DOM where the parser has already been run. If you do you'll end up with the error 'Tried to register a widget with if 'foo' but that id is already registered'.

Basically, just like IDs have to be unique for DOM nodes, they have to be unique for widgets too.

You have a couple of options:

  1. Don't return a document fragment/HTML text from your JSP. Instead, use JSON or similar and construct the new form elements programmatically in the load() callback.

  2. Do what you're doing (but make sure you've got unique IDs) but rather than using innerHTML use dojo.place(). Then keep track of the new table node you're creating and only parse that.

For example:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html dir="ltr">

    <head>
        <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css">
    </head>

    <body class="claro ">
        <div id="container">
            <table id="original">
                <tr>
                    <td>
                        <input type="text" name="first" id="first" value="testing testing" dojoType="dijit.form.TextBox" trim="true" propercase="true">
                    </td><td>
                        <input type="text" name="second" id="second" value="testing testing" dojoType="dijit.form.TextBox" trim="true" propercase="true">
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <select dojoType="dijit.form.FilteringSelect" id="third" name="third">
                            <option value="AP">
                                Apples
                            </option>
                            <option value="OR" selected>
                                Oranges
                            </option>
                            <option value="PE">
                                Pears
                            </option>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td>
                        <input id="fourth" name="fourth" dojoType="dijit.form.CheckBox" value="agreed" checked>
                        <label for="mycheck">
                            I agree
                        </label>
                    </td>
                </tr>
            </table>
        </div>
        <div>
          <button dojoType="dijit.form.Button" type="button">
              Add new fields using HTML
              <script type="dojo/method" event="onClick" args="evt">
                  dojo.xhrGet({
                      url: '_data/mockBackendForXhrBuildDomExample.php',
                      handleAs: 'text',
                      preventCache: true,
                      load: function(data) {
                          // This is a little contrived, but hopefully you get the idea
                          console.log(data);
                          var container = dojo.byId('container');
                          var newTable = dojo.place(data, container, 'last');
                          dojo.parser.parse(newTable);                          
                      },
                      error: function(error) {
                          console.error(error);
                      }
                  });
              </script>
          </button>
        </div>
    </body>

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"
    djConfig="parseOnLoad: true">
    </script>
    <script type="text/javascript">
        dojo.require("dijit.form.FilteringSelect");
        dojo.require("dijit.form.TextBox");
        dojo.require("dijit.form.CheckBox");
        dojo.require("dijit.form.Button");
        dojo.addOnLoad(function() {


        });
    </script>

</html>

I've added an example of this working at http://telliott.net/dojoExamples/dojo-xhrBuildDomExample.html. The HTML returned by the AJAX call can be found at http://telliott.net/dojoExamples/_data/mockBackendForXhrBuildDomExample.php (it uses the PHP time() function, so don't hit the button more than once a second!).

HTH,

Tom

旧城烟雨 2024-10-24 21:08:53

非常感谢汤姆的建议。我是 dojo 新手,不知道 place 功能。我改变了我的代码,我可以使用它并将新的表单字段放置在同一个 div 中。我正在使用一个使用以下 spring 标签的 jsp 片段:

<%@taglib uri="http://www.springframework.org/tags" prefix="spring" %>

<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>

当它们位于片段的最顶部时,我会收到一个 ajax 错误,指出类型不匹配。我尝试完全删除它们,但随后会放置这些字段,但没有值。我最终将它们放入开始标签中,现在一切正常。

感谢您的帮助。

Thanks a lot for the advice Tom. I am new to dojo and did not know about the place function. I changed my code around and I am able to use it and place new form fields in the same div. I am using a jsp fragment that uses the following spring tags:

<%@taglib uri="http://www.springframework.org/tags" prefix="spring" %>

<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>

When these are at the very top of the fragment I would receive an ajax error saying type mismatch. I tried removing them completely but then the fields would be placed but have no values. I ended up putting them inside the opening tag and everything works fine now.

Thanks for your help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文