【问题标题】:Using jquery-ui autocomplete in combination with dynamic form generation结合动态表单生成使用jquery-ui自动完成
【发布时间】:2015-06-17 17:14:58
【问题描述】:

我有一个可以通过使用基于this script 的js 脚本来动态更新的表单。动态生成选择列表以允许为动态生成的字段选择属性。但是,该列表包含数百个独特的属性,因此我想添加一个“搜索”框,以便更容易选择。我一直在使用 Jquery-ui 自动完成功能,当输入框位于动态更新的表单之外时,它可以正常工作,但是,一旦我将其放入表单中,它就不起作用了。以下 div 被动态插入到表单中:

<div id="readroot" style="display: none">
    <select name="_name">
        <option value="1">1</option>
        <option value="2">2</option>
        //many more options...
    </select>
    First text
    <input type="text" size="15" name="xyz" /> Second text
    <input type="text" size="15" name="xyz2" />
    <input type="button" value="Remove  trait" onclick="this.parentNode.parentNode.removeChild(this.parentNode);" />
</div>

形式:

<form method="post" name="disForm" target="_blank" id="disForm">
    <div id="writeroot"></div>
    <input type="button" value="Add trait" onclick="moreFields();" />
</form>

这是将新字段(“readroot”div)添加到“writeroot”-div 的脚本:

<script type="text/javascript">
    var counter = 0;

    function moreFields() {
        counter++;
        var newFields = document.getElementById('readroot').cloneNode(true);
        //newFields.id = '';
        newFields.style.display = 'block';
        var newField = newFields.childNodes;
        for (var i = 0; i < newField.length; i++) {
            var theName = newField[i].name
            if (theName)
                newField[i].name = theName + counter;
            newField[i].title = theName + counter;

        }
        var insertHere = document.getElementById('writeroot');
        insertHere.parentNode.insertBefore(newFields, insertHere);
    }
    window.onload = moreFields;
</script>

这是自动完成的输入和脚本:

<input title="autocomplete" name="autocomplete">

<script>
    $("[title^='autocomplete']").autocomplete({
        source: ["...many values..."]
    });
</script>

我正在使用来自 jqueryui.com 的 jQuery UI Autocomplete 1.11.4。再说一遍,这个脚本在“readroot”div 之外时有效,但在“readroot”-div 之内时无效。为什么它在“readroot”div 中不起作用?

更新我已按照 pablito.aven 的建议更正了代码。添加其他类型的可搜索列表(例如chosenjs)也可以在“readroot”div 之外工作,但不能在内部工作。自动完成脚本的工作方式如下:

<div id="readroot" style="display: none">
    <select name="_name">
        <option value="1">1</option>
        <option value="2">2</option>
        //many more options...
    </select>
    First text
    <input type="text" size="15" name="xyz" /> Second text
    <input type="text" size="15" name="xyz2" />
    <input type="button" value="Remove  trait" onclick="this.parentNode.parentNode.removeChild(this.parentNode);" />
</div>

<input title="autocomplete" name="autocomplete">//input is outside readroot, Works!

<script>
    $("[title^='autocomplete']").autocomplete({
        source: ["...many values..."]
    });
</script>

但是不是这样的:

<div id="readroot" style="display: none">
    <select name="_name">
        <option value="1">1</option>
        <option value="2">2</option>
        //many more options...
    </select>
    First text
    <input type="text" size="15" name="xyz" /> Second text
    <input type="text" size="15" name="xyz2" />
    <input type="button" value="Remove  trait" onclick="this.parentNode.parentNode.removeChild(this.parentNode);" />
 <input title="autocomplete" name="autocomplete"> //input is inside 'readroot' Does not work :(
</div>
<script>
    $("[title^='autocomplete']").autocomplete({
        source: ["...many values..."]
    });
</script>

【问题讨论】:

    标签: javascript jquery html jquery-ui autocomplete


    【解决方案1】:

    我想我现在找到了你的答案。 当您使用函数moreFields() 添加一个新选择时,您可以将readroot 中的代码复制到writeroot 之前。您正在复制代码,生成 new 元素。但是,生成自动完成的脚本已经运行了。

    <script>
        $("[title^='autocomplete']").autocomplete({
            source: ["...many values..."]
        });
    </script>
    

    因此,自动完成功能仅适用于脚本运行时已经存在的元素。

    我可能猜想,如果您从 readroot 中删除 display:none,自动完成功能将在其中起作用,但仍无法对动态生成的选择起作用。

    您应该做的是在添加更多字段时再次运行该脚本,以便它绑定到新生成的字段。这样的事情可能会奏效:

    <script type="text/javascript">
      function initializeAutocomplete(){
        $("[title^='autocomplete']").autocomplete({
          source: ["...many values..."]
        });
      }
    
      var counter = 0;
      function moreFields() {
        counter++;
        var newFields = document.getElementById('readroot').cloneNode(true);
        //newFields.id = '';
        newFields.style.display = 'block';
        var newField = newFields.childNodes;
        for (var i = 0; i < newField.length; i++) {
          var theName = newField[i].name;
          if (theName){
            newField[i].name = theName + counter;
            newField[i].title = theName + counter;
          }
        }
        var insertHere = document.getElementById('writeroot');
        insertHere.parentNode.insertBefore(newFields, insertHere);
        initializeAutocomplete();
      }
      window.onload = moreFields;
    </script>
    

    我还在if 语句中添加了{},以及缺少的一两个分号。

    如果这可行,如果您支持我的答案,我将不胜感激。如果没有,我们将不得不继续努力。

    【讨论】:

    • 太棒了。一切正常!太感谢了!在此处查看最终结果:mitodb.com
    • 这个社区有很多人帮助过我,我很高兴现在能够帮助其他人!最美好的祝愿
    【解决方案2】:

    为了在你的&lt;select&gt; 中添加一个搜索框,我使用了 angularJS,它会自动创建搜索框,而且非常简单友好。

    这样的事情会是

    <select ng-app="moduleName" ng-controller="controllerName" name="_name" id="unique_id" class="chosen-select" required>
        <option ng-repeat="x in options" value="{{x.val}}">{{x.name}}</option>
    </select>
    

    你必须用javascript初始化它。

    angular.module('moduleName', []).controller('controllerName', function($scope){
        $scope.options = [
            {val: 'value 1, 'name:'name 1'},
            {val: 'value 2', name:'name 2'},
            {val: 'value 3', name:'name 3'}
        ];
    });
    

    当您的表单以动态方式加载时,您所要做的就是弄清楚如何从您的 js 脚本中填写控制器中 $scope 变量中的选项

    为了使其正常工作,您必须包含 angularJS 源代码。

    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
    

    如果你想了解更多关于 angularJS 的工作原理,我建议你阅读它here,它不应该花费你太多时间

    【讨论】:

    • 感谢帕布利托!非常感谢您的帮助。我无法让 angularjs 使用动态更新的列表。但是,我确实让chosenjs 使用生成的列表,但仅限于“readroot”-div 之外。在'readroot' div 中它仍然不起作用。有任何想法吗?救命!
    • 我刚刚添加了一些我发现的新答案。我仍然不是 100% 理解你的问题。您介意创建一个 JSFiddle 来帮助我吗?另外,您的控制台日志中是否有任何错误?
    【解决方案3】:

    你的代码&lt;input type="button" id="moreFields" value="Add trait" onclick="init(this);" /&gt;有点小问题 在这里,您使用参数调用 init 函数。在它的定义中,它没有参数。

    function init() {
        document.getElementById('moreFields').onclick = moreFields;
        moreFields();
    }
    

    而且,如果您的 html 中已经有 onclick 属性,我不明白为什么在该 init 函数中要将 on click 事件绑定到 #moreFields。那个功能不是没必要吗?也许你可以这样做&lt;input type="button" id="moreFields" value="Add trait" onclick="moreFields();" /&gt;

    此外,您的&lt;script&gt;&lt;/script&gt; 标记中有一个html 注释行(&lt;!--)。我认为你应该删除它,它可能会造成一些麻烦。如果您想评论 javascript 代码,您应该使用 //commented line/*commented block*/

    【讨论】:

    • 感谢 Pablito,再次非常感谢您的反馈。我不知道为什么我最初有那个双重功能来运行 moreFields()。这是我一年前写的代码。无论如何,我已经按照您的建议更正了这些功能(代码在上面的示例中更新)。表单的动态生成基于this script。但是,我想让下拉菜单可以搜索,例如使用 angularjs、jquery-ui 自动完成或使用 selectedjs。但我无法让这些脚本在新生成的字段中工作。我正在尝试创建一个小提琴......
    猜你喜欢
    • 1970-01-01
    • 2011-05-31
    • 1970-01-01
    • 2011-07-23
    • 1970-01-01
    • 2018-01-18
    相关资源
    最近更新 更多