微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在MVC 4中使用jQuery更新列表

我目前正在尝试使用修改后的索引视图创建设置页面.目标是用户显示所有设置,并可以在一个视图中更改所有设置,并使用一个按钮保存所有设置.应使用Ajax更新设置.

我目前的做法:

视图:

<script language="javascript">
    $(function() {
        $('#editSettings').submit(function () {
            if ($(this).valid()) {
                $.ajax({
                    url: this.action,type: this.method,data: $(this).serialize(),success: function (result)
                    {
                        alert(result);                       
                    }
                });
            }
            return false;
        });
    });
</script>

[ ... ]

@using (Ajax.BeginForm("Edit","Settings",new AjaxOptions {UpdateTargetId = "result"},new { @class = "form-horizontal",@id = "editSettings" } ))
{
    foreach (Setting item in ViewBag.Settings) 
    {
        @Html.Partial("_SingleSetting",item)
    }
    <input type="submit" value="modify" />
}

部分视图加载设置:

<div class="control-group">
            <label class="control-label">@settingName</label>
            <div class="controls">
                @Html.EditorFor(model => model.Value)
                <span class="help-inline">@settingDescription</span>
            </div>
        </div>

模型:

[Table("Settings")]
public class Setting
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int SettingId { get; set; }

    public string Name { get; set; }

    [required(AllowEmptyStrings = true)]
    [displayFormat(ConvertEmptyStringToNull = false)]
    public string Value { get; set; }
}

我使用ViewBag.Settings = _db.Settings.ToList();设置ViewBag;

jQuery将Data解析为以下方法

[HttpPost]
    public ActionResult Edit(IList<Setting> setting)
    {
        Console.WriteLine(setting.Count);
        return Content(""); // Currently for testing purposes only. Breakpoint is set to setting.Count
    }

计数抛出错误,因为设置为空.我不太确定如何解决这个问题.

有人可以给我一个暗示吗?

关于SO的This主题已经涵盖了在没有Ajax的情况下更新集合.但我不明白这一点.

谢谢您的帮助.

解决方法

您正在使用Ajax.BeginForm并使用jQuery再次激活表单.这不是必要的.但是代码的真正问题是部分中输入字段的名称.您不尊重认模型绑定器用于绑定到列表的 naming convention.

让我们举一个完整的例子(为了简单起见,删除所有噪声,例如Entity Framework):

模型:

public class Setting
{
    public int SettingId { get; set; }
    public string Name { get; set; }
    public string Value { get; set; }
}

控制器:

public class SettingsController : Controller
{
    public ActionResult Index()
    {
        // No idea why you are using ViewBag instead of view model
        // but I am really sick of repeating this so will leave it just that way
        ViewBag.Settings = Enumerable.Range(1,5).Select(x => new Setting
        {
            SettingId = x,Name = "setting " + x,Value = "value " + x
        }).ToList();
        return View();
    }

    [HttpPost]
    public ActionResult Edit(IList<Setting> setting)
    {
        // Currently for testing purposes only. Breakpoint is set to setting.Count
        return Content(setting.Count.ToString()); 
    }
}

查看(〜/ Views / Settings / Index.cshtml):

@using (Html.BeginForm("Edit",FormMethod.Post,id = "editSettings" }))
{
    foreach (Setting item in ViewBag.Settings) 
    {
        @Html.Partial("_SingleSetting",item)
    }
    <input type="submit" value="modify" />
}

@section scripts {
    <script type="text/javascript">
        $('#editSettings').submit(function () {
            if ($(this).valid()) {
                $.ajax({
                    url: this.action,success: function (result) {
                        alert(result);
                    }
                });
            }
            return false;
        });
    </script>
}

设置部分(〜/ Views / Settings / _SingleSetting.cshtml):

@model Setting
@{
    var index = Guid.NewGuid().ToString();
    ViewData.TemplateInfo.HtmlFieldPrefix = "[" + index + "]";
}

<input type="hidden" name="index" value="@index" />

<div class="control-group">
    <label class="control-label">@Html.LabelFor(x => x.Name)</label>
    <div class="controls">
        @Html.EditorFor(model => model.Value)
    </div>
</div>

注意如何在部分内部更改HtmlFieldPrefix,以便html帮助程序为输入字段生成适当的名称并遵守命名约定.

好吧,现在让我们剪切ViewCrap并正确地做事(当然使用视图模型).

我们一如既往地编写视图模型:

public class Myviewmodel
{
    public IList<Setting> Settings { get; set; }
}

然后我们调整控制器:

public class SettingsController : Controller
{
    public ActionResult Index()
    {
        var model = new Myviewmodel();

        // you will probably wanna call your database here to 
        // retrieve those values,but for the purpose of my example that
        // should be fine
        model.Settings = Enumerable.Range(1,Value = "value " + x
        }).ToList();
        return View(model);
    }

    [HttpPost]
    public ActionResult Edit(IList<Setting> setting)
    {
        // Currently for testing purposes only. Breakpoint is set to setting.Count
        return Content(setting.Count.ToString()); 
    }
}

查看(〜/ Views / Settings / Index.cshtml):

@model Myviewmodel

@using (Html.BeginForm("Edit",id = "editSettings" }))
{
    @Html.EditorFor(x => x.Settings)
    <input type="submit" value="modify" />
}

@section scripts {
    <script type="text/javascript">
        $('#editSettings').submit(function () {
            if ($(this).valid()) {
                $.ajax({
                    url: this.action,success: function (result) {
                        alert(result);
                    }
                });
            }
            return false;
        });
    </script>
}

设置模型的编辑器模板(〜/ Views / Settings / EditorTemplates / Settings.cshtml):

@model Setting
<div class="control-group">
    <label class="control-label">@Html.LabelFor(x => x.Name)</label>
    <div class="controls">
        @Html.EditorFor(model => model.Value)
    </div>
</div>

现在按惯例工作.无需编写任何foreach循环.索引视图中的@ Html.EditorFor(x => x.Settings)调用分析视图模型的Settings属性,并检测它是某个其他模型的集合(在本例中为Setting).因此它将开始循环遍历此集合并搜索相应的编辑器模板(〜/ Views / Settings / EditorTemplates / Setting.cshtml),该模板将自动为此集合的每个元素呈现.所以你甚至不需要在视图中编写任何循环.除了简化代码之外,编辑器模板中的Html.EditorFor(x => x.Value)现在将为输入字段生成专有名称.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐