Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 4 Modal window, partial view and validation

I'm using MVC4 & Entity Framework to develop a web application. I have a table which enumerates all the persons I have in my DB. For each of them, I can edit their info throught a modal window which is a Partial View. However, when I put some wrong information, my application redirects me to my partial view. What I wanted to do is to display the errors into my modal window.

My action :

[HttpGet]
public ActionResult EditPerson(long id)
{
    var person = db.Persons.Single(p => p.Id_Person == id);

    ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name", person.Id_ProductPackageCategory);

    return PartialView("_EditPerson", person);
}

[HttpPost]
public ActionResult EditPerson(Person person)
{

    ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name", person.Id_ProductPackageCategory);

    if (ModelState.IsValid)
    {
        ModelStateDictionary errorDictionary = Validator.isValid(person);

        if (errorDictionary.Count > 0)
        {
            ModelState.Merge(errorDictionary);
            return PartialView("_EditPerson", person);
        }

        db.Persons.Attach(person);
        db.ObjectStateManager.ChangeObjectState(person, EntityState.Modified);
        db.SaveChanges();
        return View("Index");
    }

    return PartialView("_EditPerson", person);
}

My partial view :

@model BuSIMaterial.Models.Person

<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 id="myModalLabel">Edit</h3>
</div>
<div>

@using (Ajax.BeginForm("EditPerson", "Person", FormMethod.Post,
                    new AjaxOptions
                    {
                        InsertionMode = InsertionMode.Replace,
                        HttpMethod = "POST",
                        UpdateTargetId = "table"
                    }))
{

    @Html.ValidationSummary()
    @Html.AntiForgeryToken()

    @Html.HiddenFor(model => model.Id_Person)

    <div class="modal-body">
       <div class="editor-label">
            First name :
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.FirstName, new { maxlength = 50 })
            @Html.ValidationMessageFor(model => model.FirstName)
        </div>
        <div class="editor-label">
            Last name :
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.LastName, new { maxlength = 50 })
            @Html.ValidationMessageFor(model => model.LastName)
        </div>
        <div class="editor-label">
            National number :
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.NumNat, new { maxlength = 11 })
            @Html.ValidationMessageFor(model => model.NumNat)
        </div>
        <div class="editor-label">
            Start date :
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.StartDate, new { @class = "datepicker", @Value = Model.StartDate.ToString("yyyy/MM/dd") })
            @Html.ValidationMessageFor(model => model.StartDate)
        </div>
        <div class="editor-label">
            End date :
        </div>
        <div class="editor-field">
            @if (Model.EndDate.HasValue)
            {
                @Html.TextBoxFor(model => model.EndDate, new { @class = "datepicker", @Value = Model.EndDate.Value.ToString("yyyy/MM/dd") })
                @Html.ValidationMessageFor(model => model.EndDate)
            }
            else
            {
                @Html.TextBoxFor(model => model.EndDate, new { @class = "datepicker" })
                @Html.ValidationMessageFor(model => model.EndDate)
            }
        </div>
        <div class="editor-label">
            Distance House - Work (km) :
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.HouseToWorkKilometers)
            @Html.ValidationMessageFor(model => model.HouseToWorkKilometers)
        </div>
        <div class="editor-label">
            Category :
        </div>
        <div class="editor-field">
            @Html.DropDownList("Id_ProductPackageCategory", "Choose one ...")
            @Html.ValidationMessageFor(model => model.Id_ProductPackageCategory) <a href="../ProductPackageCategory/Create">
                Add a new category?</a>
        </div>
        <div class="editor-label">
            Upgrade? :
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Upgrade)
            @Html.ValidationMessageFor(model => model.Upgrade)
        </div>
    </div>
    <div class="modal-footer">
        <button class="btn btn-inverse" id="save" type="submit">Save</button>
    </div>
}

</div>

My script which is in the Index view :

        $('.edit-person').click(function () {
               var id = $(this).data("id");
               var url = '/Person/EditPerson/'+id;
               $.get(url, function(data) {

                   $('#edit-person-container').html(data);
                   $('#edit-person').modal('show');

               });
        });

Also, as you can see, I have put a size for my textboxes but in my modal, it seems to not be taken into account. Any ideas for these issues?

like image 918
Traffy Avatar asked Apr 15 '13 13:04

Traffy


1 Answers

You have to manually fire the validator on your form that was loaded dynamically into your html page.

try this:

in your view use Ajax.ActionLink to load the content of the partial view into your dialog container to avoid unnecessary JavaScript.

@Ajax.ActionLink("AjaxLink", "EditPerson", new { PersonID = model.Id_Person }, new AjaxOptions { UpdateTargetId = "myModalDialog", HttpMethod = "Post",OnSuccess="OpenDialog(myModalDialog)" })

<div id="myModalDialog" title="" style="display: none">
</div>

in you JS file do this

function OpenDialog(DialogContainerID)
{
     var $DialogContainer = $('#' + DialogContainerID);
     var $jQval = $.validator; //This is the validator
     $jQval.unobtrusive.parse($DialogContainer); // and here is where you set it up.
     $DialogContainer.modal();

     var $form = $DialogContainer.find("form");
     $.validator.unobtrusive.parse($form);

     $form.on("submit", function (event)
     {
             var $form = $(this);

             //Function is defined later...
             submitAsyncForm($form,
             function (data)
             {
                     $DialogContainer.modal("hide");
                     window.location.href = window.location.href;

             },
             function (xhr, ajaxOptions, thrownError)
             {
                     console.log(xhr.responseText);
                     $("body").html(xhr.responseText);
             });
             event.preventDefault();
     });
}

//This is the function that will submit the form using ajax and check for validation errors before that.
function submitAsyncForm($formToSubmit, fnSuccess, fnError)
{
        if (!$formToSubmit.valid())
                return false;

        $.ajax({
                type: $formToSubmit.attr('method'),
                url: $formToSubmit.attr('action'),
                data: $formToSubmit.serialize(),

                success: fnSuccess,
                error: fnError

        });

}
like image 89
Mortalus Avatar answered Sep 21 '22 01:09

Mortalus