JQuery - 克隆datepicker和select2

时间:2016-02-11 13:10:35

标签: javascript jquery jquery-ui datepicker

昨天我问了一个类似的问题,但经过几次补充之后,事情似乎变成了梨形。我有一些HTML采用以下形式

<div class="form-group">
    <div class="row">
        <div class="col-md-12">
            <div class="col-md-12">
                <table class="table table-bordered" id="actionTable">
                    <tbody>
                    <tr id='actionRow1'>
                        <td>
                          <input type="text" name='actionInput[0][action]' id="actionInput"  placeholder='Action' class="form-control"/>
                        </td>
                        <td>
                          <select class="responsibility" name='actionInput[0][responsibility]' id="responsibilityInput">
                                <option value="One">One</option>
                                <option value="Two">Two</option>
                                <option value="Three">Three</option>
                            </select>
                        </td>
                        <td>
                          <input type="text" name='actionInput[0][deliveryDate]' id="dateInput" placeholder='Completion Date' class="form-control dateControl"/>
                        </td>
                      </tr>
                    </tbody>
                </table>
                <a id="add_row" class="btn btn-default pull-right">Add Row</a>
                <a id='delete_row' class="pull-right btn btn-default">Delete Row</a>
            </div>
        </div>
    </div>
</div>

因此它有一个文本输入,一个选择和另一个日期文本。输入的名称是2D数组,因为我需要稍后以特定的方式处理这些数据。

无论如何,当单击Add Row按钮时,它应克隆整个tr。这包括销毁select2和datepicker,以及更新新输入的名称和ID。为此,我有以下JS

$(function() {
    $('#add_row').on('click', function(evt){addRow();});
    $('#delete_row').on('click', function(evt){deleteRow();});
});

function addRow() {

    $("table tr#actionRow1").eq(0).clone().each(function(tr_idx, tr_elem) {

        $(".dateControl").datepicker("destroy");

        $(".responsibility").select2("destroy");

        var
            $tr = $(tr_elem),
            newRowIdx = $("table tr").length;

        $tr.attr('id', 'actionRow' + newRowIdx);

        $tr.find("input, select").each(function(i_idx, i_elem) {

            var $input = $(i_elem);

            if($input.attr('id') == 'actionInput') {
                $(this).val("");
            }

            if ($input.hasClass('dateControl')) {
                $(this).val("");
            }

            $input.attr({
                'id': function(_, id) {
                    return id + newRowIdx;
                },
                'name': function(_, id) {
                    return id.replace('[0]', '['+ newRowIdx +']');
                },
                'value': ''
            });
        });

        $(".dateControl").datepicker({
            dateFormat: "dd-mm-yy"
        });

        $(".responsibility").select2({
            tags: true
        });

    }).appendTo("table");
}

function deleteRow() {
    curRowIdx = $("table tr").length;
    if (curRowIdx > 1) {
        $("#actionRow" + (curRowIdx - 1)).remove();
        curRowIdx--;
    }
}

我已设置以下JSFiddle来演示。

在小提琴中,我不得不注释掉destroy方法,否则会抛出错误。第一个问题,第一次访问时,datepicker和select2不起作用。单击“添加行”时,前一行的datepicker和select2将起作用,但新行不起作用。所以它有点延迟。 一旦开始添加多行,它就决定在某些行中添加多个选择框。不太清楚为什么会这样。

对此进行整理的任何建议都非常赞赏。

谢谢

1 个答案:

答案 0 :(得分:1)

调用$(".dateControl").datepicker();将尝试在与DOM中当前匹配的".dateControl"匹配的所有元素上初始化一个datepicker小部件。因此,在第一次点击时,您可以在第一行初始化它(但不是在您正在克隆的那一行上,因为它还没有被附加!)。添加的第三行然后重新初始化第一行上的datepicker并在第二行上初始化它,等等。对于另一个小部件。您应该将匹配器限制为仅当前正在处理的行:

$(".dateControl", $tr).datepicker({
  dateFormat: "dd-mm-yy"
});

$(".responsibility", $tr).select2({
  tags: true
});

如果你这样做,你根本不需要destroy电话。另外,请确保明确地将这些内容称为第一行(请参阅NicolasR&#39;

此外,datepicker会创建一个新的table元素,因此您需要在使用表选择器的任何位置定位自己的表。否则,addRow函数将在您第一次打开日期选择器后停止工作(即将新表附加到DOM,并且"table"行中的appendTo选择器启动匹配它):https://jsfiddle.net/r94pkLLb/3/