1

I have a View in which Items ( modelview) created/deleted dynamically using BeginCollectionItem and partialview. The dynamically created view's validation is not firing. Code: MainView :

 @model EnquiryVM
    @using (Html.BeginForm()) 
    {
        @Html.AntiForgeryToken()

        <div class="form-horizontal">

            @Html.ValidationSummary(true, "", new { @class = "text-danger" })

            <div class="form-group">
                @Html.LabelFor(model => model.EnquiryNumber, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-3">
                    @Html.EditorFor(model => model.EnquiryNumber, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.EnquiryNumber, "", new { @class = "text-danger" })
                </div>
            </div>



            <div class="form-group">
                @Html.LabelFor(model => model.DivisionID, "Division", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-3">
                    @Html.DropDownListFor(u => u.DivisionID, (IEnumerable<SelectListItem>)Model.Divisions, "--Select--") 
                    @Html.ValidationMessageFor(model => model.DivisionID, "", new { @class = "text-danger" })
                </div>
            </div>



            <div id="LineItems">
                @using (Html.BeginForm())
                {
                    <div id="editorRowsLineitems">
                        @foreach (var item in Model.LineItems)
                        {
                            @Html.Partial("_CreateEnquiryItem", item)
                        }
                    </div>
                    @Html.ActionLink("Add Items", "CreateLineItem", null, new { id = "addItem", @class = "button" });
                }
            </div>
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Create" class="btn btn-default" />
                </div>
            </div>
        </div>
    }


    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    <script type="text/javascript">
        $(function () {
            $('#addItem').on('click', function () {
                $.ajax({
                    url: '@Url.Action("CreateLineItem")',
                        cache: false,
                        success: function (html) { $("#editorRowsLineitems").append(html); }
                    });
                    return false;
                });
            $('#editorRowsLineitems').on('click', '.deleteRow', function () {
                    $(this).closest('.editorRow').remove();
                });
            $('form').data('validator', null);
            $.validator.unobtrusive.parse($('form'));
        });


    </script>
    }

PartialView :

@model EnquiryLineItemVM

<div class="editorRow">
    @using (Html.BeginCollectionItem("ItemList"))
    {
        <table class="table">

            @Html.ValidationSummary(true, "", new { @class = "text-danger" })

            <tr>
                <td>
                    @Html.EditorFor(model => model.ItemDesc)
                    @Html.ValidationMessageFor(model => model.ItemDesc, "", new { @class = "text-danger" })
                </td>
                <td>
                    @Html.EditorFor(model => model.Quantity)
                    @Html.ValidationMessageFor(model => model.Quantity, "", new { @class = "text-danger" })
                </td>

                <td>
                    @Html.DropDownListFor(model => model.ManufacturerId, Model.ManufacturerList, "--Please Select--")
                    @Html.ValidationMessageFor(model => model.ManufacturerId, "", new { @class = "text-danger" })
                </td>
                <td>

                    <a href="#" class="deleteRow">Delete</a>
                </td>
            </tr>
        </table>

    }
    </div>

ViewModel:

 public class EnquiryLineItemVM
    {
        public int ID { get; set; }
        [Required]
        public string ItemDesc { get; set; }
       [Required]
        public int Quantity { get; set; }

    }

Similar question which uses validation in such scenario is here SO1 But didn't work . I have referenced unobtrusive and Jquery validations in the view. Please help. Thanks for reading .

user2695433
  • 2,013
  • 4
  • 25
  • 44
  • Possible duplicate of [A Partial View passing a collection using the Html.BeginCollectionItem helper](https://stackoverflow.com/questions/40539321/a-partial-view-passing-a-collection-using-the-html-begincollectionitem-helper) –  Sep 18 '17 at 22:34
  • You need to reparse the validator in after the html for the new item has been added. i.e. in the success callback - just as per the answer you linked to (which does work). Your currently doing it only when the page is forst rendered which is pointless. –  Sep 18 '17 at 22:36
  • And you still have not fixed all the other errors you have as noted in your [previous question](https://stackoverflow.com/questions/46277135/using-begincollectionitem-for-adding-deleting-lineitems-in-mvc5-partialview) –  Sep 18 '17 at 22:38
  • @StephenMuecke . Thanks again . Its not that I have ignored the point regarding removing Validation Summary from the PartialView. I had tried keeping it and removing it but neither of them worked , actually I had placed the reparsing script you provided outside the success function. My mistake. now it works perfectly. both when validation summary is there in partial view and without too. Thanks a lot for the help extended – user2695433 Sep 19 '17 at 05:03
  • Its not just the `@Html.ValidationSummary` - its the invalid nested forms and the incorrect name in `BeginCollectionItem()` –  Sep 19 '17 at 05:33
  • @StephenMuecke the other points I had taken cared off yesterday itself. It would be nice if you can add these points as a brief answer so that I can mark it as an accepted. All I could do was +1 ed all your points in the comments :-) – user2695433 Sep 19 '17 at 05:38
  • I'll add an answer to that one in an hour or 2 –  Sep 19 '17 at 05:39
  • @StephenMuecke thanks again – user2695433 Sep 19 '17 at 05:42

1 Answers1

3

Jquery validation doesn't work when you dynamically add to the DOM because it adds attributes used in validation. The workaround is to call it again after you load:

$('#addItem').on('click', function () {
    $.ajax({
        url: '@Url.Action("CreateLineItem")',
            cache: false,
            success: function (html) { 
                           $("#editorRowsLineitems").append(html); 
                           // clear and add validation attributes
                           $("form").removeData("validator");
                           $("form").removeData("unobtrusiveValidation");
                           $.validator.unobtrusive.parse("form");
                      }
        });
        return false;
    });

See here

Steve Greene
  • 12,029
  • 1
  • 33
  • 54