验证不适用于克隆的元素

Validation not working on cloned elements

如果我像这样创建多个元素...

@for (int i = 0; i < 10; i++)
{
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Railcars[i].RailcarNumber" class="control-label"></label>
                <input asp-for="Railcars[i].RailcarNumber" class="form-control" />
                <span asp-validation-for="Railcars[i].RailcarNumber" class="text-danger"></span>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Railcars[i].Weight" class="control-label"></label>
                <input asp-for="Railcars[i].Weight" class="form-control" />
                <span asp-validation-for="Railcars[i].Weight" class="text-danger"></span>
            </div>
        </div>
    </div>
}

验证似乎对所有行都有效。

但是,如果我像这样创建一行...

<div class="railcars">
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Railcars[0].RailcarNumber" class="control-label"></label>
                <input asp-for="Railcars[0].RailcarNumber" class="form-control" />
                <span asp-validation-for="Railcars[0].RailcarNumber" class="text-danger"></span>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Railcars[0].Weight" class="control-label"></label>
                <input asp-for="Railcars[0].Weight" class="form-control" />
                <span asp-validation-for="Railcars[0].Weight" class="text-danger"></span>
            </div>
        </div>
    </div>
</div>

然后使用 jQuery 的 clone() 克隆行,验证似乎只适用于第一行(非克隆)。

注意:我正在注意更新所有 IDnamefor 克隆元素的属性,并更新下标号。我检查它是否正确并将正确的信息发布到服务器。 ModelState 甚至可以正确检测克隆元素的验证问题。只是客户端验证对它们不起作用。

这里是HTML产生的:

未克隆行(验证有效):

<div class="row first-railcar">
    <div class="col-md-4">
        <div class="form-group railcar-number">
            <label class="control-label" for="Railcars_0__Railcar">Railcar Number</label>
            <input class="form-control" type="text" data-val="true" data-val-length="The field Railcar Number must be a string with a maximum length of 18." data-val-length-max="18" data-val-required="The Railcar Number field is required." id="Railcars_0__Railcar" maxlength="18" name="Railcars[0].Railcar" value="">
            <span class="text-danger field-validation-valid" data-valmsg-for="Railcars[0].Railcar" data-valmsg-replace="true"></span>
        </div>
    </div>
    <div class="col-md-4">
        <div class="form-group railcar-volume">
            <label class="control-label" for="Railcars_0__Volume">Volume (pounds)</label>
            <input class="form-control" type="text" data-val="true" data-val-number="The field Volume (pounds) must be a number." data-val-required="The Volume (pounds) field is required." id="Railcars_0__Volume" name="Railcars[0].Volume" value="">
            <span class="text-danger field-validation-valid" data-valmsg-for="Railcars[0].Volume" data-valmsg-replace="true"></span>
        </div>
    </div>
    <div class="col-md-4">
        <div class="form-group">
            <label class="control-label">&nbsp;</label><br>
            <img class="add-railcar" src="/images/add.png" title="Add Additional Railcar" style="display: none;">
            <img class="remove-railcar" src="/images/delete_2.png" title="Remove Railcar" style="display: none">
        </div>
    </div>
</div>

克隆行(验证无效):

<div class="row">
    <div class="col-md-4">
        <div class="form-group railcar-number">
            <label class="control-label" for="Railcars_1__Railcar">Railcar Number</label>
            <input class="form-control" type="text" data-val="true" data-val-length="The field Railcar Number must be a string with a maximum length of 18." data-val-length-max="18" data-val-required="The Railcar Number field is required." id="Railcars_1__Railcar" maxlength="18" name="Railcars[1].Railcar" value="">
            <span class="text-danger field-validation-valid" data-valmsg-for="Railcars[1].Railcar" data-valmsg-replace="true"></span>
        </div>
    </div>
    <div class="col-md-4">
        <div class="form-group railcar-volume">
            <label class="control-label" for="Railcars_1__Volume">Volume (pounds)</label>
            <input class="form-control" type="text" data-val="true" data-val-number="The field Volume (pounds) must be a number." data-val-required="The Volume (pounds) field is required." id="Railcars_1__Volume" name="Railcars[1].Volume" value="">
            <span class="text-danger field-validation-valid" data-valmsg-for="Railcars[1].Volume" data-valmsg-replace="true"></span>
        </div>
    </div>
    <div class="col-md-4">
        <div class="form-group">
            <label class="control-label">&nbsp;</label><br>
            <img class="add-railcar" src="/images/add.png" title="Add Additional Railcar">
            <img class="remove-railcar" src="/images/delete_2.png" title="Remove Railcar" style="">
        </div>
    </div>
</div>

我还仔细比较了上面克隆的 HTML 和我的第一个示例(使用 for 循环)创建的 HTML,它们是相同的。显然,在页面加载后添加它有一些不同。

有人知道如何以这种方式克隆元素并对所有克隆元素进行验证吗?

更新:

我对 jQuery 的 clone() 的使用包括两个真值 ($row.clone(true, true))。如果我不这样做,我的图像的点击处理程序将不起作用。

按照建议,我在克隆元素后尝试了以下代码的几种变体。但我无法让它产生任何影响。

var form = document.getElementById('input-form');
$.validator.unobtrusive.parse(form);

$.validator.unobtrusive.parse(form); 的方向是正确的。但是,要使 jQuery 验证在具有 ajax/cloned 元素的 copied/appended 上工作,您需要三件事。

  • 确保每个输入元素都有唯一的名称。
  • 删除现有元素形式的所有先前验证绑定。
  • 重新创建验证绑定。

下面是一个工作示例。

<form>

    <div class="container" id="ElementContainer">

        <div id="ElementToClone">

            <div class="row">
                <div class="col col-md-4">
                    <div class="form-group">

                        <input class="form-control" type="text" name="elem[0]" id="elem_0" data-val="true" data-val-required="Required.">

                    </div>
                </div>
            </div>

        </div>

    </div>

    <div class="pt-3">
        <button type="button" class="btn btn-primary" onclick="Clone()">Clone</button>
        <button type="submit" class="btn btn-primary ml-3">Submit</button>
    </div>

</form>

<script>
    function Clone() {
        var $container = $('#ElementContainer');
        var $elem = $('#ElementToClone');
        var $form = $container.closest('form');

        //duplicate x times
        for (var i = 1; i <= 5; i++) {
            var clonedHtml = $elem.html();

            //create a unique name
            clonedHtml = clonedHtml.replace('elem[0]', 'elem[' + i + ']');

            //create an unique id (not required for validate to function)
            clonedHtml = clonedHtml.replace('elem_0', 'elem_' + i);

            //append the cloned element
            $container.append(clonedHtml);
        }

        //remove validation from the inital input elements or it won't work
        $form.removeData('validator').removeData('unobtrusiveValidation');

        //bind the validation again
        $.validator.unobtrusive.parse($form);
    }
</script>

P.S。在 MVC 上测试,而不是 Core。但它应该工作相同,因为它无论如何都是前端。