0

I've been fighting this for a while and I think I'm close. I am new to MVC and am after the mcguffin of web design, all the model handling (including validation) with partial views (not update the whole page). My current method (below) 'works' until there is an ajax postback (I get the partial back using ajax). The problem is the client validation works before I press the Create button and repopulate the Partial View. I test this by clearing out the 'Age' textbox and pressing Create. I get the message saying the field is required. Then I enter a valid value int the field and press Create again and 'post' back. Now, when I clear the Age box again, the error message does not show up and it lets me post with an invalid value showing. Can anyone tell me why it will not work after I hit the 'Create' (id=yourSubmitButtonID) button?

Also, if anyone knows a better way to do this please let me know.

PartialController.cs

using StuffTesterMVC.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace StuffTesterMVC.Controllers
{
    public class PartialController : Controller
    {
        // GET: Partial
        public ActionResult Partials()
        {
            return View();
        }

        public PartialViewResult GetModel01()
        {
            PartialViewModel01 model = new PartialViewModel01();
            model.Birthday = DateTime.Parse("9/10/1964");
            return PartialView("PartialViewModel01", model);
        }
    }
}

Partials.cshtml

@{
    Layout = null;
}

<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Partials</title>
</head>
<body>
    <div id="divPartial01"> 
        @Html.Partial("PartialViewModel01", new StuffTesterMVC.Models.PartialViewModel01())
    </div>
    @*<div id="divPartial02">
        @Html.Partial("PartialViewModel02", new StuffTesterMVC.Models.PartialViewModel02())
    </div>*@
    <!-- SCRIPTS -->
    <script>
        function saveSampleModel01() {
            alert('posting');
            $.ajax({
                url: "@Url.Action("GetModel01", "Partial")",
                type: "post",  // make this "get" to get data
                data: $("#divPartial01").serialize(),
                success: function (result) {
                    $("#divPartial01").html(result);
                    alert('success');
                },
                error: function (result) {
                    err: alert("Failed");
                }
            });
        }
    </script>
</body>
</html>

PartialViewModel01.cshtml

@model StuffTesterMVC.Models.PartialViewModel01

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

    <div class="form-horizontal">
        <h4>PartialViewModel01</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Age, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Age, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Age, "", new { @class = "text-danger" })
            </div>
        </div>

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

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

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="button" id="yourSubmitButtonID" value="Create" class="btn btn-default" />
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="button" value="Save" onclick="saveSampleModel01();" class="btn btn-default" />
            </div>
        </div>
    </div>
    <script>
        $(function () {
            $("#yourSubmitButtonID").click(function (e) {
                e.preventDefault();
                var _this = $(this);
                var _form = _this.closest("form");

                alert('validating');

                var validator = $("form").validate(); // obtain validator
                var anyError = false;
                _form.find("input").each(function () {
                    if (!validator.element(this)) { // validate every input element inside this step
                        anyError = true;
                    }
                });

                if (anyError) {
                    alert('found errors');
                    return false; // exit if any error found    
                }

                alert('no errors - do "post"');
                saveSampleModel01();
                //$.post(_form.attr("action"), _form.serialize(), function (data) {
                    //check the result and do whatever you want
                })
            });
    </script>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
Belmiris
  • 2,741
  • 3
  • 25
  • 29
  • what _exactly_ "stops working"? And what happens instead? An error somewhere (maybe in the browser console)? Or some different behaviour? Also your Partial has a dependency on the parent view (the call to `saveSampleModel01()`). This kind of defeats the point of partials (i.e. that they can be used repeatedly, and in multiple views). – ADyson Apr 05 '17 at 15:36
  • After the page is first loaded, you can clear the Age box and the validation will tell you that the field is required. If you fill in the Age field and press post back (press the Create button), the client side validation stops working and it lets you post anything. The alert('no error - do post') is shown no matter what. As for the button, I'm just trying to figure out how these partials views are supposed to work. – Belmiris Apr 05 '17 at 18:13
  • You need to re-parse the validator after adding dynamic content - refer [this answer](http://stackoverflow.com/questions/31768946/required-field-validations-not-working-in-jquery-popup-mvc-4/31769058#31769058). And scripts should not be in partials - move it to your main view. –  Apr 05 '17 at 22:52
  • Ah, that worked! Thank you. I am having trouble figuring out how all this is working. We are at a level of javascript programming that is way beyond me. I will need to learn more before I am comfortable. If you make this an answer I will mark it as resolved and give you credit. – Belmiris Apr 06 '17 at 13:45
  • Possible duplicate of [Required field validations not working in JQuery Popup MVC 4](http://stackoverflow.com/questions/31768946/required-field-validations-not-working-in-jquery-popup-mvc-4) –  Apr 07 '17 at 08:35

1 Answers1

0

As Stephen Muecke indicated, I resolved this by adding the line:

$.validator.unobtrusive.parse(form);

to my javascript in PartialViewModel01.cshtml.

I guess it was a duplicate question: Earlier question

Community
  • 1
  • 1
Belmiris
  • 2,741
  • 3
  • 25
  • 29