2013-03-01 35 views
2

我目前正在嘗試使用修改的索引視圖創建設置頁面。目標是用戶獲得所有設置顯示,並可以更改所有設置在一個視圖和保存所有設置使用一個單一按鈕。該設置應該使用Ajax進行更新。如何更新列表<Model>與jQuery在MVC 4

我目前的做法:

查看:

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

jQuery的解析數據,以以下的方法設置ViewBag:

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

Count因爲設置是null引發錯誤。我很不確定如何解決這個問題。

有人可以給我一個提示嗎?

This SO上的主題已經涵蓋了更新沒有Ajax的Collection。但我不明白這一點。

謝謝你的幫助。

回答

12

您正在使用Ajax.BeginForm,並再次使用jQuery將表單再次渲染。這沒有必要。但你的代碼真正的問題是你的部分輸入字段的名稱。您不尊重默認模型聯編程序用於綁定列表的naming convention

讓我們一個完整的示例(去除所有噪音,如實體框架爲簡單起見):

型號:

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", "Settings", FormMethod.Post, new { @class = "form-horizontal", 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, 
        type: this.method, 
        data: $(this).serialize(), 
        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, 5).Select(x => new Setting 
     { 
      SettingId = x, 
      Name = "setting " + x, 
      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", "Settings", FormMethod.Post, new { @class = "form-horizontal", 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, 
        type: this.method, 
        data: $(this).serialize(), 
        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)調用分析視圖模型的設置屬性,並檢測它是某個其他模型的集合(在這種情況下爲Setting)。因此,它將開始循環瀏覽這個集合並搜索相應的編輯器模板(~/Views/Settings/EditorTemplates/Setting.cshtml),該模板將自動爲該集合的每個元素呈現。所以你甚至不需要在視圖中編寫任何循環。除了簡化代碼之外,編輯器模板中的Html.EditorFor(x => x.Value)現在將爲輸入字段生成專有名稱。

+0

非常感謝您的詳細解答。這給了我一個關於EditorTemplates的完整的新視圖*,以及與視圖結合使用的List <>。 – 2013-03-04 08:40:33