如何使用JavaScript而不是提交按钮发布ASP.NET MVC Ajax表单

46

我有一个使用Ajax.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" />
<% }%>

控制器已连接并返回更新DescriptionDiv的部分视图。一切顺利。

现在,我希望能够提交此表单,而无需使用提交按钮(通过单击链接、图像或其他任何方式)。不幸的是,这个小的jQuery代码片段无法完成任务:

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

它确实提交了表单,但是(我认为不足为奇地)是一个常规的后台提交,而不是Ajax提交。

为了简化起见,上述jQuery代码如下连接:

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

这个表单的onsubmit事件使用了Sys.Mvc.AsyncForm.handleSubmit(),但是jQuery的submit似乎绕过了它。

PS. 我正在寻找针对这种特定方法的解决方案。我知道如何使用普通表单并使用AJAX+jQuery进行提交来实现相同的效果。但我对于这个特定的解决方案很感兴趣。

8个回答

41
我假设你在选择器周围缺少引号只是一个转录错误,但你应该检查一下。此外,我没有看到你实际上给表单分配了一个ID。通常你可以使用htmlAttributes参数来完成这个操作,但我没有看到你使用它。不过,如果表单确实提交了,这可能就是一个转录错误。
如果选择器和ID不是问题所在,那么我怀疑问题可能是因为使用Ajax BeginForm扩展时通过标记添加了单击处理程序。您可以尝试使用 $('form').trigger('submit') 或者在最坏的情况下,让锚点上的单击处理程序创建一个在表单中点击的隐藏提交按钮。甚至使用纯jQuery创建自己的ajax提交(这可能是我会做的事情)。
最后,您应该意识到,通过替换提交按钮,您将完全破坏不能启用javascript的人的用户体验。解决这个问题的方法是同时使用 noscript 标签隐藏一个按钮,并在服务器上处理AJAX和非AJAX请求。
顺便说一句,值得注意的是,除了微软之外,将事件处理程序添加到javascript而不是标记中是标准做法。这样可以让您将javascript组织在一个地方,以便更容易地查看表单上正在发生的情况。以下是我如何使用触发机制的示例。
  $(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>
<% } %>

14
$('form#ajaxForm').submit(); 可以在jQuery 1.4.4和MVC 3中使用,但我花了很长时间才发现你需要引用一些脚本文件,否则这将退回到常规的后台提交。在我的情况下,这些文件是:jquery.unobtrusive-ajax.(min.)js + MicrosoftAjax和MicrosoftMvcAjax。 - juhan_h
1
如果将 .submit() 更改为 .trigger('submit');,它并不能解决问题。 - Levitikon
4
加载jquery.unobtrusive-ajax.(min.)js对我也有帮助。 - twk
如果我需要在这种情况下绕过表单验证,该如何实现? - Vad
@tvanfosson 我有一个名为“删除地址”的链接,调用JS执行一些操作,然后进行回传。此链接不需要验证。而我有一个“保存”提交按钮需要验证。我不想完全禁用客户端验证。 - Vad
显示剩余4条评论

7
一个简单的示例,当下拉列表发生变化时,会触发ajax表单提交以重新加载数据网格:
<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>

关键是trigger('onsubmit'):它调用MVC添加到表单上的onsubmit函数。

NB. UserSearchResults控制器返回一个PartialView,使用提供的Model渲染表格。

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

@Abel,你确定你的编辑是正确的吗?我记得当时它非常明确地是trigger('onsubmit'),而不是trigger('submit')。 - James McCormack
好的,我尝试了你的解决方案,使用 onsubmit 引发了一个 JS 错误,而使用 submit 则没有。就这么简单。虽然我没有更深入地思考它。 - Abel

6

不幸的是,在所有浏览器中都不能触发onsubmit或submit事件。

  • 在IE和Chrome中有效:#('form#ajaxForm')trigger('onsubmit');
  • 在Firefox和Safari中有效:#('form#ajaxForm')trigger('submit');

此外,如果您在Chrome或IE中触发('submit'),它会导致整个页面被发布,而不是执行AJAX行为。

适用于所有浏览器的方法是删除onsubmit事件行为并仅在表单本身上调用submit()

<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> 
<% } %>

此外,为了使其起作用,链接并不必须包含在表单中。

1
一个 Eval,真的吗?这是一个安全噩梦。为什么这么难? - Levitikon

3

我曾尝试多次使ajax表单提交正常工作,但总是要么完全失败,要么妥协太多。这里有一个页面示例,它在MVC页面内使用jQuery Form插件来更新项目列表(使用部分渲染控件),当用户在输入框中输入时:

<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>

在控制器端:

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);
}

谢谢您提供的示例,但我正在努力解决这个特定问题 - 正如我所指出的,我已经使用jQuery找到了另一种解决方案,但我不能使用它。 - mfloryan

2
尝试以下方法:
<input type="submit" value="Search" class="search-btn" />
<a href="javascript:;" onclick="$('.search-btn').click();">Go</a>

<input type="submit" value="搜索" class="search-btn" /> <a href="javascript:;" onclick="$('.search-btn').click();">前往</a> - Dinesh Kumar

2

Ajax.BeginForm 看起来似乎失败了。

使用普通的 Html.BeginForm,可以完美地解决问题:

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

0

与其使用JavaScript,不妨尝试一些类似的东西

<a href="#">

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

</a>

0

只需在Ajax.BeginForm中放置普通按钮,点击时查找父表单并进行普通提交。 Razor中的Ajax表单:

@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>
    }

以及JavaScript:

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

    $formToSubmit.submit();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接