Search code examples
asp.net-core-mvcunobtrusive-validation

Dynamically created elements are not validated on the client


I have a table in my web application, which is populated from the model, where properties have attribute for validation:

    [Required(ErrorMessage = "Please enter amount!")]
    [DisplayFormat(NullDisplayText = "", ApplyFormatInEditMode = true)]
    public decimal? Amount { get; set; }

When I press Submit, the field is properly validated on the client, displaying an error message, if the amount is left empty.

Now the user can add new TRs to the table using jquery. The new record completely imitates the existing records, e.g. when I inspect the Amount field for an existing TR:

<input class="form-control" type="text" data-val="true" data-val-number="The field Amount must be a number." data-val-required="Please enter amount!" id="Financials_1__Amount" name="Financials[1].Amount" value="1834.09"><span class="text-danger field-validation-valid" data-valmsg-for="Financials[1].Amount" data-valmsg-replace="true"></span>

Cf. to the same field of the dynamically added TR:

<input class="form-control" type="text" data-val="true" data-val-number="The amount must be a number." data-val-required="Please enter amount!" id="Financials_77e9f261-010a-4c7c-ae50-e3f6587a8c4e__Amount" name="Financials[77e9f261-010a-4c7c-ae50-e3f6587a8c4e].Amount" value="33"><span class="text-danger field-validation-valid" data-valmsg-for="Financials[77e9f261-010a-4c7c-ae50-e3f6587a8c4e].Amount" data-valmsg-replace="true"></span>

The records look very similar. Yet when I leave the required field empty and press submit, the value is not validated on the client, and the execution comes to the controller's action method. There ModelState.IsValid is false though. This is my first issue.

Here is the action method:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Edit(int contractorId, ContractorDetailsDto dto)
    {
        if (ModelState.IsValid)
        {
  ...
        }

        return View(_contractorRepository.GetContractorDetailsViewModelByDto(dto));
    }

As our ModelState is invalid, the same view is loaded. There the error is displayed in the validation summary, BUT NOT UNDER THE FIELD WITH THE INVALID VALUE. This is the second issue.

I have on my view:

@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

How can I find the cause of my problems?


Solution

  • Answering for your main question. Can you try to execute next javascript code after you add new row

    function refreshValidators(formSelector) {
        var targetForm = $(formSelector);
        targetForm.removeData('validator');
        targetForm.removeData('unobtrusiveValidation');
        targetForm.removeAttr('novalidate');
        $.validator.unobtrusive.parse(targetForm);
    }
    

    Regarding your second problem I think you should create separate question for it as it unrelated to your main question. You need to find proper way how to add new rows in ASP.NET Core. For ASP.NET MVC we had next solution how to solve this task http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/ . After googling BeginCollectionItem I found core analog solution, but it is pretty old and I didnt use it personaly.