2016-03-14 55 views
5

我是一位經驗豐富的.NET C#軟件開發人員,但僅在幾個月前我開始使用MVC Razor(MVC 5)。MVC Razor創建要提交的對象列表

我有一個小的情況下,我找不到任何答案,在網上(搜索的時段後)

我有了另一種模式的一個列表,它反過來也有一個列表中選擇模型一個模型如下所示。

public class Parent 
{ 
    public string Name { get; set; } 
    public string Sex { get; set; } 
    public int Age { get; set; } 
    public List<Child> Children { get; set; } 
} 

public class Child 
{ 
    public string Name { get; set; } 
    public string Sex { get; set; } 
    public int Age { get; set; } 
    public List<GrandChild> GrandChildren { get; set; } 
} 

public class GrandChild 
{ 
    public string Name { get; set; } 
    public string Sex { get; set; } 
    public int Age { get; set; } 
} 

和我的控制器有2種方法,一種是主要的獲取,另一種是後才能發佈新的數據

public ActionResult Index() 
{ 
    return View(); 
} 

[HttpPost] 
public ActionResult PostParent(Parent parent) 
{ 
    if (ModelState.IsValid) 
    { 
     //Do an insert to the DB 
     return View("~/Views/Home/Index.cshtml"); 
    } 

    return Json("Error"); 
} 

但是在我的表視圖,我不能找到一種方法要創建一個附加按鈕,插入新的數據子孫的名單(櫃面一個兒童)

@using (Html.BeginForm("PostParent", "Home", FormMethod.Post, new {@class = "form-horizontal", role = "form"})) 
{ 
    @Html.LabelFor(x => x.Name) 
    @Html.TextBoxFor(x => x.Name) 
} 

我只能添加字段爲基本類型性質在,但不適合的對象。

我真的很感激任何幫助!

+0

請參閱答案[這裏](http://stackoverflow.com/questions/29161481/post-a-form-array-without-successful/29161796#29161796)和[這裏](http://stackoverflow.com /問題/ 28019793 /提交 - 同局部視圖所謂-多次數據到控制器/ 28081308#28081308)。請注意,您不能將'BeginCollectionItem'用於嵌套集合 –

+0

並且有關動態創建嵌套集合的工作示例,請參閱[此DotNetFiddle](https://dotnetfiddle.net/wqE6Rb) –

回答

2

我想你需要一個通常的標準<input/>,你應該從HTML5知道。 如果我正確地理解了你,你想把視圖中的數據傳遞給控制器​​。現在你應該需要一個按照你創建的形式的按鈕。 您需要/應該通過將模型數據從視圖傳遞給Controller來調用Controller。 @Html.ActionLink()是剃刀幫手<Input>

事情是這樣的形式內部可能應該做的伎倆:

@Html.ActionLink("Click here to pass", "ActionName", new { ParameterNameOfTheController = Model }) 

背後的東西的邏輯應該在控制器發生。 我希望這可以幫助你。

+0

嗨H. Senkaya 是的,我已經有了提交按鈕,並且邏輯在控制器中,但是,我想知道如何創建新列表並從視圖添加項目到列表中,所以當我單擊提交時,數據將在那裏。 –

2

我做了一個與您的場景相關的項目。但是,我找不到剃鬚刀的解決方案。所以我結束了使用SheepIt jquery插件來動態添加字段。

https://github.com/mdelrosso/sheepit

確保你堅持ID和ASP MVC理解名模式。

<input class="form-control text-box single-line" id="sheepItForm_#index#__Field" name="sheepItForm[#index#].Field" type="text" value="" /> 
 
<span class="field-validation-valid text-danger" data-valmsg-for="sheepItForm[0].Field" data-valmsg-replace="true"></span>

希望這有助於!

+0

嗨Vish J 嗯,我實際上找到了一種解決方案,使用純JavaScript將項目添加到列表並堅持使用mvc命名模式。但是如果你有大型複雜的嵌套對象,這將花費太多時間。 –

7

爲此,您可以使用Html.BeginCollectionItemhttps://www.nuget.org/packages/BeginCollectionItem/

你可以做的是對主窗體視圖並通過Parent模型它,因爲這將代表家長,那麼你將需要一個行代表一個孩子,你可以稱之爲ChildRow.cshtml

所以對於我們正在創建的父母Create.cshtml查看我們將通過父母模型。

@model Parent 

@using(Html.BeginForm()) 
{ 
    @Html.TextBoxFor(m => m.Name) 


    <table id="children"> 
     <tbody> 

<!-- This here will display the Child Row for existing Rows in the Parent model --> 

      @foreach (var child in Model.Children) 
      { 
       @Html.Partial("ChildRow", child) 
      } 
     </tbody> 

    </table> 
<button type="button" id="addChild">Add Child</button> 

<button type="submit"> Save</button> 
    } 

然後這就是ChildRow.cshtml的樣子,它將有一個Child模型。

注意:您必須將IsDeleted屬性添加到子模型中,這將有助於您在控制器中查看子項是否被刪除或不是。

@model Child 

@using (Html.BeginCollectionItem("Children")) 
{ 
    <tr> 
     <td> 
      @Html.HiddenFor(m => m.IsDeleted, new { data_is_deleted = "false" }) 
      @Html.HiddenFor(m => m.ChildId) 
      @Html.TextBoxFor(m => m.Name) 
     </td> 

     <td> 
      <span class="glyphicon glyphicon-trash action-icon" data-action="removeItem"></span> 
     </td> 


    <tr> 
} 

現在你必須單擊該按鈕Add Child時將行添加到表的末尾。

爲此,您將創建一個控制器中的新動作:

public ActionResult AddChild() 
    { 
     return PartialView("Child", new Child()); 
    } 

,然後添加這個jQuery到Create.cshtml

$("#addChild").on("click", function() { 
     $.ajax({ 
      url: '@Url.Action("AddChild", "YourController")' 
     }).success(function (partialView) { 
      $('#children> tbody:last-child').append(partialView); 
     }); 
    }); 

這將一個新的子行追加到表

如果你想在同一頁面上刪除,你也必須隱藏/禁用該行,因爲你可以添加這個jQuery:

$('body').on("click", '*[data-action="removeItem"]', function (e) { 
    e.stopPropagation(); 
    var btn = $(this); 
    var row = btn.closest('tr'); 
    var firstCell = $(row.find('td')[0]); 
    var checkBox = firstCell.find('*[data-is-deleted]'); 
    var checkBoxVal = checkBox.val(); 

    if (checkBoxVal === 'False' || checkBox.val() === 'false') { 
     checkBox.val('true'); 
     row.find('td').find('input, textarea, select').attr('readonly', 'readonly'); 
    } else { 
     checkBox.val('false'); 
     row.find('td').find('input, textarea, select').attr("readonly", false); 
    } 

}); 

然後,當您回發給控制器時,您將看到模型中的兒童列表。

[HttpPost] 
public ActionResult Create(Parent model) 
{ 

    var newChildren = model.Children.Where(s => !s.IsDeleted && s.ChildId == 0); 

    var updated = model.Children.Where(s => !s.IsDeleted && s.ChildId != 0); 

    var deletedChildren = model.Children.Where(s => s.IsDeleted && s.ChildId != 0); 


    return View(model); 
} 

你必須爲GrandChildren做類似的事情。

+1

哇,實際工作,感謝你的例子現在我有更好的瞭解如何使用Html.BeginCollectionItem。 標記爲答案:) –