2013-11-21 56 views
3

我的應用程序中有一個非常大的表單,其中有很多不同的輸入和我的模型中的很多列表。所以我會嘗試添加/刪除列表而不將完整的模型發送到服務器。將動態創建的元素綁定到視圖中的複雜mvc模型

我嘗試了幾種方法,但我沒有找到一個乾淨的方法。你可以想象我的模型是這樣的:

public class EditSomething 
{ 
    public string name { get; set;} 

    public List<something> somethingList { get; set;} 

    // a lot other fields... 

    public EditSomething(EditSomethingFromDatabase editSomethingFromDatabase) 
    { 
     name = editSomethingFromDatabase.Name; 
     somethingList = new List<SomethingModel>(); 
     foreach(var something in editSomethingFromDatabase.Something) 
     { 
      somethingList.Add(new SomethingModel(editSomethingFromDatabase.Something)); 
     } 
    } 
} 

其他模型看起來相似但沒有列表。

在視圖我對模型的表:

<h2>Something</h2> 
    <div id="SomethingDiv"> 
     <table id="SomethingTable"> 
      <thead> 
       <tr> 
        <th>@Html.Label("SomethingName")</th> 
        <th>@Html.Label("SomethingID")</th> 
               <th></th> 
       </tr> 
      </thead> 
      <tbody id="SomethingTableBody"> 

       @Html.EditorFor(x => x.somethingList) 

      </tbody> 
     </table> 
     <p> 
      <input type="button" name="addSomething" value="Add Something" id="AddSomething"> 
     </p> 
    </div> 

的addSomething的jQuery是:

$('#AddSomething').click(function() { 
     $.ajax({ 
      url: '@Url.Action("AddSomething", "SomethingModels")', 
      data: { tableSize: $('#SomethingTable tr').length }, 
      cache: false, 
      success: function (html) { $('#SomethingTable tr:last').after(html); } 
     }); 

控制器方法AddSomething是:

public ActionResult AddSomething (int tableSize) 
{ 
    SomethingModel something= new SomethingModel(null, (-2) * (tableSize + 1)); 
    return PartialView(""~/Views/EditorTemplates/EditSomethingModel.cshtml"", something); 
} 

而至少我在EditorTemplates中有一個編輯器模板,用於editorfor和partialview。這是我所要發送到服務器的重要信息:

@model SomethingModel 
<tr>@TextBoxFor(m=>m.SomethingName)<td> 

@TextBoxFor(M => m.SomethingID)

所以,現在的問題是,該提交的第一個視圖的唯一崗位SomethingModel到服務器誰已經存在,同時打開視圖,但從AddMutation方法新的SomethingModel不在崗位。有人想解決這個問題嗎?

編輯:改變了編輯模板的路徑,所以我只需要EditorForPartialView的一個視圖。

Edit2:爲了解決主要問題,我創建了一個視圖,並將其用作部分視圖。現在數據正確地發送到服務器。僅在客戶端驗證仍然沒有工作:

@model SomethingModel 
    <tr>@TextBoxFor(m=>m.SomethingName, new{Name="somethingList["+ViewBag.ListId+"].SomethingName")<span class="field-validation-valid" data-valmsg-for="somethingList[@ViewBag.ListId].SomethingName" data-valmsg-replace="true"></span><td> 
<tr>@TextBoxFor(m=>m.SomethingID, new{Name="somethingList["+ViewBag.ListId+"].SomethingID")<span class="field-validation-valid" data-valmsg-for="somethingList[@ViewBag.ListId].SomethingID" data-valmsg-replace="true"></span><td> 
</tr> 

AddSomething方法我在列表中的下一個元素的ID添加ViewBag.ListId

+0

我已經改變了我的答案與你需要得到驗證不引人注目的變化在ajax回調後使用新的字段。 –

+0

是的,看。但是您需要從您要提交的表單中刪除所有驗證。這將工作:var table ='$('#SomethingForm')。removeData(「validator」)。removeData(「unobtrusiveValidation」); $ .validator.unobtrusive.parse(table);'非常感謝 –

回答

2

這似乎是一個足夠合理的做法,但你無法看到您的EditorTemplate,所以我會承擔起這樣的:

@model List<something> 

@for(int i = 0; i < Model.Count; i++) 
{ 
    <tr> 
    <td>@Html.DisplayFor(m => m[i].Id) @Html.HiddenFor(m => m[i].Id)</td> 
    <td>@Html.EditorFor(m => m[i].Name)</td> 
    </tr> 
} 

你的AJAX方法應返回一行的HTML - 和這很重要...表格字段需要在表格中的最後一個之上命名爲1。

所以,當你查看錶的渲染源(添加任何新的領域之前,它可能看起來像:

... 
<tbody> 
    <tr> 
    <td>1 <input type="hidden" name="something[0].Id" value="1"/></td> 
    <td><input type="text" name="something[0].Name" value="somename" /></td> 
    </tr> 
</tbody> 

您需要確保由AJAX方法爲新行返回的HTML是:

<tr> 
    <td>2 <input type="hidden" name="something[1].Id" value="2"/></td> 
    <td><input type="text" name="something[1].Name" value="somenewname" /></td> 
    </tr> 

即,括號內的數字是東西中項目的下一個索引,如果索引中存在間隙(或它們重疊),則新項目不會被解析。

編輯 - 讓客戶端驗證爲新的領域改變你的jQuery的ajax成功回調如下工作:

$('#AddSomething').click(function() { 
    $.ajax({ 
     url: '@Url.Action("AddSomething", "SomethingModels")', 
     data: { tableSize: $('#SomethingTable tr').length }, 
     cache: false, 
     success: function (html) { 
      $('#SomethingTable tr:last').after(html); 
      $.validator.unobtrusive.parse('#SomethingTable'); 
     } 
    }); 
+0

我改變了我的問題中的代碼。最後一個代碼示例是編輯器模板。我使用'EditorFor'來顯示somethingList中的每個元素。 mvc helper自動爲列表中的每個項目創建一個viw,所以你不需要使用循環。 另外我的ajax方法返回了一行的HTML,但是你的權利,它不使用列表中的數字。而不是'​​'我只把它創建爲'​​'。所以,謝謝你,我會檢查如何改變這一點。 –

+0

@James如果你在索引上有空白,可以說因爲你有一個減號按鈕來刪除動態html,我怎麼還能解析整個集合? – Zinov

+0

@Zinov你需要一些JavaScript來重新索引所有的領域後,比刪除的一個。您不能在客戶端字段索引中留下間隙,否則它們在回發時不會被解析。例如'',然後定義一個javascript函數來刪除行,並通過索引更高的行集合 - 替換全部[rowindex]與[rowindex -1]的實例 –