MVC 5 Ajax表单,异步更新字段并仍然支持完整表单帖子

时间:2015-11-12 00:19:15

标签: ajax asp.net-mvc

所以我一直在使用MVC但不是很多Ajax。 所以我的问题是我有一个创建视图,其中创建视图的第一个字段是日期选择器,在更改时我希望ajax更改窗体上另一个字段的选择下拉列表。我有Ajax更新工作,但表单Post(创建按钮),现在只调用控制器上的Ajax方法。我希望Ajax发布回调用Controller上的默认方法Create方法。因此,创建表单包含3个字段

  1. 日期(提交OnChange Ajax)
  2. ID和文字的下拉列表
  3. 所需的其他字段
  4. 我已经包含了模型和cshtml视图文件(其中一个是部分文件)。控制器只是一个采用日期时间值或整个模型的方法。 所以我让代码工作在哪里,当日期改变时它会更新相关的LocalIds字段,但因为'创建'按钮位于Ajax.BeginForm标记内,当按下创建按钮时,它会生成一个Ajax调用,我希望它生成一个Form Post。我缺少什么

    CreateModel

    public class IdsSelection
    {
        public string Id { get; set; }
        public List<SelectListItem> Selections { get; set; }
    }
    
    public class CreateModel
    {
        [Display(Name="Local Id's")]
        public IdsSelection LocalIds;
        [Display(Name="Day")]
        [Required, DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}",ApplyFormatInEditMode=true)]
        public DateTime Date { get; set; }
        [Required, Display(Name = "Other Value")]
        [Range(1.0, 1000000.0, ErrorMessage ="Value must be greater than zero")]
        public decimal OtherValue { get; set; }
    
        public CreateModel()
        {
            Date = DateTime.Today;
        }
    }
    

    CreateView.cshtml

    @Model Demo.Models.CreateModel
    ....
    @using (Ajax.BeginForm("ChangeDate", "Process", new AjaxOptions()
    {
        InsertionMode = InsertionMode.Replace,
        HttpMethod = "GET",
        UpdateTargetId = "changeid",
    }))
    {
        @Html.AntiForgeryToken()
        <div class="form-horizontal">
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                @Html.LabelFor(model => model.Date, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Date, new
               {
                   htmlAttributes = new
                   {
                       autofocus = "autofocus",
                       @class = "form-control",
                       @Value = Model.Date.ToString("yyyy-MM-dd"),
                       onchange = "$(this.form).submit();"
                   }
               })
                @Html.ValidationMessageFor(model => model.Date, "", new { @class = "text-danger" })
                </div>
            </div>
    
            @Html.Partial("_ShowIds", Model.LocalIds)
    
            <div class="form-group">
                @Html.LabelFor(model => model.OtherValue, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.OtherValue, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.OtherValue, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Create" class="btn btn-default" />
                </div>
            </div>
        </div>
    }
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
    
    @section Scripts {
        <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
    }
    

    _ShowIds.cshtml

    @model Demo.Models.IdsSelection
    
    <div id="changeid" class="form-group">
        @Html.Label("Local Id", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
    
            @if(Model.Selections.Count == 1)        // one
            {
                @Html.HiddenFor(model => model.Id)
                @Html.EditorFor(model => model.Selections[0].Text, new
                {
                    htmlAttributes = new
                    {
                        @class = "form-control",
                        @readonly = "readonly",
                    }
                })
            }
            else            // more entries so show a dropdown
            {
                @Html.DropDownListFor(model => model.Id, Model.Selections, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model, "", new { @class = "text-danger" })
            }
            </div>
        </div>
    

1 个答案:

答案 0 :(得分:1)

您尚未向控制器方法显示,但假设生成此视图的方法名为Create(),则创建相应的POST方法

[httpPost]
public ActionResult Create(CreateModel model)

用于保存数据。删除@using (Ajax.BeginForm("ChangeDate", "Process", new AjaxOptions() { ..... ]))并替换为普通表单以回发到服务器(您可以删除jquery.unobtrusive-ajax.min.js

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

接下来,创建一个控制器方法,根据所选日期返回部分视图

public PartialViewResult FetchLocalIds(DateTime date)
{
  IdsSelection model = // populate model based on selected date
  return PartialView("_ShowIds", model);
}

接下来,在视图中,将当前@Html.Partial()包装在占位符元素

<div id="localids">
    @Html.Partial("_ShowIds", Model.LocalIds)
</div>

然后使用jquery处理datepickers .change()事件,并调用FetchLocalIds()方法使用.load()函数更新DOM。

$('#Date').change(function() {
  $('#localids').load('@Url.Action("FetchLocalIds")', { date: $(this).val() })
})

还请注意从onchange = "$(this.form).submit();"

中删除@Html.EditorFor(model => model.Date, new { ... })