将jquery-ui自动完成与动态表单生成结合使用

时间:2015-06-17 17:14:58

标签: javascript jquery html jquery-ui autocomplete

我有一个可以使用基于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>

我正在使用Autocomplete 1.11.4中的jQuery UI jqueryui.com。只是为了重复一遍,这个脚本在“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>

3 个答案:

答案 0 :(得分:1)

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

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

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

我可能会猜测,如果您从display:none移除readroot,则自动填充功能会在其中生效,但仍然无法处理动态生成的选择。

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

<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语句,以及一个或两个丢失的分号。

如果这样有效,如果你赞成我的答案,我将感激不尽。如果它没有,我们将不得不继续尝试。

答案 1 :(得分:0)

如果在<select>内有一个搜索框,我会使用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'}
    ];
});

当你的表单加载dinamically时,你所要做的就是弄清楚如何从你的js脚本填充控制器中$ scope变量的选项

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

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

如果您想了解更多有关angularJS的工作原理,我建议您阅读它here,它不会花太多时间

答案 2 :(得分:0)

您的代码<input type="button" id="moreFields" value="Add trait" onclick="init(this);" />存在轻微问题 在这里,您可以使用参数调用init函数。在它的定义中,它不需要参数。

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

并且,我不明白为什么在你的html中已经有onclick属性的那个init函数你将点击事件绑定到#moreFields。这个功能不是不必要的吗?也许你可以做<input type="button" id="moreFields" value="Add trait" onclick="moreFields();" />

此外,您的<!--代码中还有一条html评论专栏(<script></script>)。我认为你应该删除它,它可能会造成一些麻烦。如果您想对javascript代码发表评论,则应使用//commented line/*commented block*/

进行评论