web-dev-qa-db-fra.com

Comment publier un formulaire ASP.NET MVC Ajax à l'aide de JavaScript plutôt que du bouton d'envoi

J'ai un formulaire simple créé avecAjax.BeginForm:

<% using (Ajax.BeginForm("Update", "Description", new { id = Model.Id },
     new AjaxOptions
     {
       UpdateTargetId = "DescriptionDiv",
       HttpMethod = "post"
     },new {id ='AjaxForm' })) {%>
Description:
<%= Html.TextBox("Description", Model.Description) %><br />
<input type="submit" value="save" />
<% }%>

Le contrôleur est câblé et renvoie une vue partielle qui met à jour la DescriptionDiv. Et tout fonctionne parfaitement.

Maintenant, j'aimerais pouvoir envoyer ce formulaire sans le bouton d'envoi (via un clic sur un lien, une image ou autre). Malheureusement, ce petit fragment jQuery ne fait pas le travail:

$('form#AjaxForm').submit();

Il soumet le formulaire, mais (je suppose sans surprise) un post-back régulier et non un formulaire Ajax.

Par souci de simplicité, jQuery ci-dessus est câblé comme suit:

<a href="#" onclick="$('form#AjaxForm').submit(); return false;">submit</a>

Le formulaire du formulaire utilise la méthode Sys.Mvc.AsyncForm.handleSubmit (), mais la soumission de jQuery semble ignorer cela.

PS. Je cherche une solution dans cette approche particulière. Je sais comment réaliser la même chose en utilisant un formulaire normal et en l'affichant avec AJAX + jQuery. Je suis intéressé par cette solution particulière cependant.

43
mfloryan

Je suppose que votre absence de guillemets autour du sélecteur est simplement une erreur de transcription, mais vous devriez quand même vérifier. De plus, je ne vois pas où vous donnez réellement un identifiant à la forme. En général, vous faites cela avec le paramètre htmlAttributes. Je ne vous vois pas utiliser la signature qui l'a. Encore une fois, cependant, si le formulaire est soumis, cela pourrait être une erreur de transcription.

Si le sélecteur et l'id ne sont pas le problème, je soupçonne que c'est peut-être parce que le gestionnaire de clics est ajouté via le balisage lorsque vous utilisez l'extension Ajax BeginForm. Vous pouvez essayer d'utiliser $ ('formulaire'). Trigger ('soumettre') ou, dans le pire des cas, demander au gestionnaire de clic sur l'ancre de créer un bouton de soumission masqué dans le formulaire et de cliquer dessus. Ou même créer votre propre soumission ajax en utilisant jQuery pur (ce qui est probablement ce que je ferais).

Enfin, sachez qu'en remplaçant le bouton de soumission, vous allez totalement casser le tout pour les personnes qui ne disposent pas de javascript. Pour contourner ce problème, vous devez également masquer un bouton à l'aide d'une balise noscript et gérer les publications AJAX et non-AJAX sur le serveur.

BTW, il est considéré comme une pratique standard, sans tenir compte de Microsoft, d’ajouter les gestionnaires via javascript et non via des balises. Votre javascript reste ainsi organisé afin que vous puissiez plus facilement voir ce qui se passe sur le formulaire. Voici un exemple d'utilisation du mécanisme de déclenchement.

  $(function() {
      $('form#ajaxForm').find('a.submit-link').click( function() {
           $('form#ajaxForm').trigger('submit');
      }).show();
  }

<% using (Ajax.BeginForm("Update", "Description", new { id = Model.Id },
     new AjaxOptions
     {
       UpdateTargetId = "DescriptionDiv",
       HttpMethod = "post"
     }, new { id = "ajaxForm" } )) {%>
   Description:
   <%= Html.TextBox("Description", Model.Description) %><br />
   <a href="#" class="submit-link" style="display: none;">Save</a>
   <noscript>
       <input type="submit" value="Save" />
   </noscript>
<% } %>
38
tvanfosson

Un exemple simple, dans lequel une modification dans une liste déroulante déclenche un envoi de formulaire ajax pour recharger une grille de données:

<div id="pnlSearch">

    <% using (Ajax.BeginForm("UserSearch", "Home", new AjaxOptions { UpdateTargetId = "pnlSearchResults" }, new { id="UserSearchForm" }))
    { %>

        UserType: <%: Html.DropDownList("FilterUserType", Model.UserTypes, "--", new { onchange = "$('#UserSearchForm').trigger('submit');" })%>

    <% } %>

</div>

Le déclencheur ('onsubmit') est l’essentiel: il appelle la fonction onsubmit que MVC a greffée sur le formulaire.

NB Le contrôleur UserSearchResults renvoie un PartialView qui affiche une table à l'aide du modèle fourni.

<div id="pnlSearchResults">
    <% Html.RenderPartial("UserSearchResults", Model); %>
</div>
7
James McCormack

Malheureusement, le déclenchement des événements onsubmit ou submit ne fonctionnera pas dans tous les navigateurs.

  • Fonctionne dans IE et Chrome: # ('form # ajaxForm') trigger ('onsubmit');
  • Fonctionne dans Firefox et Safari: # ('form # ajaxForm') trigger ('submit');

De plus, si vous déclenchez ("submit") dans Chrome ou IE, la page entière sera publiée au lieu de procéder au comportement AJAX. 

Ce qui fonctionne pour tous les navigateurs est supprimer le comportement de l’événement onsubmit et appeler simplement submit () sur le formulaire lui-même .

<script type="text/javascript">
$(function() {

    $('form#ajaxForm').submit(function(event) { 
        eval($(this).attr('onsubmit')); return false; 
        });

    $('form#ajaxForm').find('a.submit-link').click( function() { 
        $'form#ajaxForm').submit();
        });

  }
</script>
  <% using (Ajax.BeginForm("Update", "Description", new { id = Model.Id },
     new AjaxOptions
     {
       UpdateTargetId = "DescriptionDiv",
       HttpMethod = "post"
     }, new { id = "ajaxForm" } )) {%>
   Description:
   <%= Html.TextBox("Description", Model.Description) %><br />
   <a href="#" class="submit-link">Save</a> 
<% } %>

En outre, le lien ne doit pas nécessairement être contenu dans le formulaire pour que cela fonctionne.

6
Brian Reiter

J'ai essayé à plusieurs reprises de faire en sorte que le formulaire ajax fonctionne correctement, mais j'ai toujours rencontré un échec complet ou trop de compromis. Voici un exemple de page qui utilise le plug-in jQuery Form à l'intérieur d'une page MVC pour mettre à jour une liste de projets (à l'aide d'un contrôle partiellement rendu) lorsque l'utilisateur tape dans une zone de saisie:

<div class="searchBar">
    <form action="<%= Url.Action ("SearchByName") %>" method="get" class="searchSubmitForm">
        <label for="projectName">Search:</label>
        <%= Html.TextBox ("projectName") %>
        <input class="submit" type="submit" value="Search" />
    </form>
</div>
<div id="projectList">
    <% Html.RenderPartial ("ProjectList", Model); %>
</div>

<script type="text/javascript">
    jQuery(document).ready(function() {
        jQuery("#projectName").keyup(function() {
            jQuery(".searchSubmitForm").submit();
        });

        jQuery(".searchSubmitForm").submit(function() {
            var options = {
                target : '#projectList'
            }

            jQuery(this).ajaxSubmit(options);

            return false;
        });

        // We remove the submit button here - good Javascript depreciation technique
        jQuery(".submit").remove();
    });
</script>

Et du côté du contrôleur:

public ActionResult SearchByName (string projectName)
{
    var service = Factory.GetService<IProjectService> ();
    var result = service.GetProjects (projectName);

    if (Request.IsAjaxRequest ())
        return PartialView ("ProjectList", result);
    else
    {
        TempData["Result"] = result;
        TempData["SearchCriteria"] = projectName;

        return RedirectToAction ("Index");
    }
}

public ActionResult Index ()
{
    IQueryable<Project> projects;
    if (TempData["Result"] != null)
        projects = (IQueryable<Project>)TempData["Result"];
    else
    {
        var service = Factory.GetService<IProjectService> ();
        projects = service.GetProjects ();
    }

    ViewData["projectName"] = TempData["SearchCriteria"];

    return View (projects);
}
3
Kieron

Ajax.BeginForm semble être un échec.

En utilisant un fichier Html.Begin normal, cela fait très bien l'affaire:

$('#detailsform').submit(function(e) {
    e.preventDefault();
    $.post($(this).attr("action"), $(this).serialize(), function(r) {
        $("#edit").html(r);
    });
}); 
2
Levitikon

Essayez de la manière suivante:

<input type="submit" value="Search" class="search-btn" />
<a href="javascript:;" onclick="$('.search-btn').click();">Go</a>
2
Dinesh Kumar

Il suffit de placer le bouton normal dans Ajax.BeginForm, puis de cliquer sur le formulaire parent, puis de le soumettre. Ajax forme dans Razor:

@using (Ajax.BeginForm("AjaxPost", "Home", ajaxOptions))
    {        
        <div class="form-group">
            <div class="col-md-12">

                <button class="btn btn-primary" role="button" type="button" onclick="submitParentForm($(this))">Submit parent from Jquery</button>
            </div>
        </div>
    }

et Javascript:

function submitParentForm(sender) {
    var $formToSubmit = $(sender).closest('form');

    $formToSubmit.submit();
}
0
Rostislav Štryncl

Plutôt que d'utiliser JavaScript, essayez peut-être quelque chose comme: 

<a href="#">

  <input type="submit" value="save" style="background: transparent none; border: 0px none; text-decoration: inherit; color: inherit; cursor: inherit" />

</a>
0
Benjamin