web-dev-qa-db-fra.com

Comment créer un formulaire MVC .NET dans un modal à l'aide de jQuery avec validation

J'ai vraiment du mal à savoir comment mettre tout cela ensemble. J'ai construit des formulaires à l'intérieur de pages MVC .net à de nombreuses reprises, avec et sans validation. Et j'ai construit des formulaires en utilisant jQuery, avec et sans validation. Et j'ai construit des formes à l'intérieur d'un modal, mais jamais avec MVC.

Je comprends de ma question d'origine que parce que ce formulaire est à l'intérieur d'un modal que je devrai utiliser jQuery pour gérer la soumission. J'ai beaucoup de temps à trouver comment assembler toutes ces pièces en mouvement. Jusqu'à présent, je n'ai pas trouvé de tutoriel (ou combo de tutoriels) qui rassemble tout cela.

Voici ce dont j'ai besoin:

  • À l'intérieur de ma vue MVC, il y a un bouton qui ouvre un modal. (Cela fonctionne très bien.)
  • Une fois le modal ouvert, il contient un formulaire avec plusieurs champs de texte et listes déroulantes. Chacun est requis. (Pour rendre les champs obligatoires, devrais-je les définir dans le modèle de la vue, comme je le ferais normalement avec un formulaire MVC? Ou dois-je créer les exigences dans jQuery?)
  • Si l'utilisateur tente de soumettre le formulaire et qu'ils sont vides ou invalides, le modal reste ouvert et les messages de validation apparaissent. (Je comprends, d'après ma question d'origine , que cela n'est pas possible en utilisant directement MVC à cause du modal, et que certains jQuery sont nécessaires. Je suis perdu ici.)
  • Si l'utilisateur tente de soumettre le formulaire et que tous les champs sont valides, le modal se ferme, nous frappons le contrôleur et enregistrons les champs dans la base de données. (Je ne sais pas comment sortir du jQuery et juste frapper le contrôleur normal pour gérer la logique finale.)

MODIFIER:

Merci, Jason, pour votre aide! Sur la base de vos suggestions, c'est ainsi que je l'ai fait fonctionner.

La vue parent:

Le modal:

<div class="modal fade" id="AccountEditModal" tabindex="-1" role="dialog" aria-labelledby="AccountEditModalLabel">
    <div class="modal-dialog modalAccountEdit" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h3><strong>Edit Account Profile - <span class="accountname"></span></strong></h3>
            </div>

            <div class="modal-body">
                <div id="formContent">
                    @Html.Partial("_AccountProfileEdit", new GEDCPatientPortal.Models.AccountProfileEditViewModel())
                </div>
            </div>
        </div>
    </div>
</div>

Et puis voici les scripts:

@section Scripts {
    <script>
        $(document).ready(function () {

            $('#AccountEditModal').on('shown.bs.modal', function () {
                $('#myInput').focus()
            })



        $("#AccountEditModal").on("submit", "#form-accountprofileedit", function (e) {
            e.preventDefault();  // prevent standard form submission

            var form = $(this);
            $.ajax({
                url: form.attr("action"),
                method: form.attr("method"),  // post
                data: form.serialize(),
                success: function (partialResult) {
                    $("#formContent").html(partialResult);
                }
            });
        });


        });

    </script>
}

La vue partielle (allégée):

@using (Html.BeginForm("AccountProfileEdit", "Account", FormMethod.Post, new { id = "form-accountprofileedit", @class = "full-form" }))
    {


    @Html.CustomTextboxFor(model => model.Address)


    <div style="text-align:right;">
        <button type="submit" id="accountprofileedit-submit" name="accountprofileedit-submit" value="Edit Account" class="btn btn-primary" style="margin-left:5px;">Edit Account</button>
        <button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
    </div>
}

Le contrôleur:

    [HttpPost]
    public ActionResult AccountProfileEdit(AccountProfileEditViewModel model)
    {
        if (ModelState.IsValid)
        {
            // logic to store form data in DB
        }

        return PartialView("_AccountProfileEdit", model);

    }
20
Casey Crookston

Vous pouvez utiliser les scripts de validation MVC intégrés avec les annotations de données sur votre modèle

public class AccountProfileEditViewModel
{
    [Display(Name = "Address")]
    [Required()]
    [StringLength(200)]
    public string Address { get; set; }
}

Faites une vue partielle pour conserver votre formulaire modal.

_ AccountProfileEdit.cshtml

@model AccountProfileEditViewModel

@using(Html.BeginForm("AccountProfileEdit", "Account",
           FormMethod.Post, new { id = "form-accountedit-appt" }) {
    @Html.ValidationSummary(true)

    @Html.LabelFor(m => m.Address)
    @Html.TextBoxFor(m => m.Address)
    @Html.ValidationMessageFor(m => m.Address)
    <button type="submit">Edit</button>
}

Référencez ensuite cela dans votre boîte modale. Si vous voulez un modèle pré-rempli, vous devrez rendre une action:

<div class="modal-body" id="form-container">
    @Html.Action("AccountProfileEdit", "Account", new { id=account.Id })
</div>

Si vous voulez juste un formulaire vierge, vous pouvez simplement utiliser:

<div class="modal-body" id="form-container">
    @Html.Partial("_AccountProfileEdit")
</div>

L'action utilise le paramètre id pour récupérer et remplir le modèle

[HttpGet]
public ActionResult AccountProfileEdit(int id)
{
    AccountProfileEditViewModel model = db.GetAccount(id);  // however you do this in your app

    return PartialView("_AccountProfileEdit", model);
}

AJAX POST

Vous aurez maintenant besoin de AJAX pour soumettre ce formulaire. Si vous comptez sur une soumission de formulaire standard, le navigateur s'éloignera de votre page (et fermera votre modal).

$("#myModal").on("submit", "#form-accountedit", function(e) {
    e.preventDefault();  // prevent standard form submission

    var form = $(this);
    $.ajax({
        url: form.attr("action"),
        method: form.attr("method"),  // post
        data: form.serialize(),
        success: function(partialResult) {
            $("#form-container").html(partialResult);
        }
    });
});

Vous devez utiliser le délégué d'événement $(staticParent).on(event, target, handler) pour l'événement d'envoi, car le contenu du formulaire peut être remplacé ultérieurement.

Après l'action

[HttpPost]
public ActionResult AccountProfileEdit(AccountProfileEditViewModel model)
{
    // Request.Form is model

    if (ModelState.IsValid)
    {
        // do work
        return PartialView("_AccountEditSuccess");
    }

    return PartialView("_AccountProfileEdit", model);
}

Les scripts de validation côté client devraient les empêcher de se soumettre. Mais si cela échoue ou si vous ne pouvez pas valider quelque chose sur le client, vous avez ModelState.IsValid. Vous pouvez également invalider manuellement quelque chose côté serveur.

_ AccountEditSuccess.cshtml

Et la vue partielle "succès".

<div>Success! <button>Click to close</button></div>

Non valide est un échec, non?

Depuis votre gestionnaire de réussite AJAX

success: function(partialResult) {
    $("#form-container").html(partialResult);
}

Mais le problème ici est que nous ne savons pas si vous obtenez un "succès" ou un "échec de validation". L'ajout d'un gestionnaire error: function(err){ } n'aidera pas car l'échec de la validation est considéré comme une réponse HTTP 200 . Dans les deux cas, le contenu div est remplacé, l'utilisateur devra fermer manuellement le modal. Il existe des moyens de transmettre des données supplémentaires pour distinguer les deux conditions, mais c'est une autre réponse longue.

34
Jasen

Pensez à mettre un iframe à l'intérieur de la division modale, au lieu de rendre partialView, de cette façon, vous pouvez développer la section modale de la même manière que vous développez des pages simples, qui soumettent, modélisent, requis, etc.

par ici:

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog modalAE" role="document">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h3><strong>Edit Account Profile - <span class="accountname"></span></strong></h3>
        </div>
            <div class="modal-body">
          <iframe src='myApp/AccountProfileEdit'/>
        </div>
        <div class="modal-footer">
            <button type="submit" id="accountprofileedit-submit" name="accountprofileedit-submit" value="Edit Account" class="btn btn-primary" style="margin-left:5px;">Edit Account</button>
            <button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
        </div>
        }
    </div>
</div>
3
Elisheva Wasserman