2016-03-14 6 views
5

Ich bin ein erfahrener .NET C# Software Entwickler, aber erst vor ein paar Monaten begann ich mit MVC Razor (MVC 5).MVC Razor erstellen Liste von Objekten zum Einreichen

Ich habe eine kleine Situation, die ich keine Antwort auf auf dem Netz (nach Stunden des Suchens)

Ich habe ein Modell, das eine Liste von einem anderen Modell hat, die wiederum auch eine Liste finden konnte von ein Modell wie unten gezeigt.

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; } 
} 

und mein Controller verfügt über zwei Methoden, eine Haupt ist importieren, und das andere ist Post, um neue Daten zu schreiben

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"); 
} 

jedoch meiner Ansicht nach in der Form, ich kann nicht einen Weg finden, ein Add-Taste und legen Sie neue Daten in die Liste der Kinder und Enkel (incase eines Kindes)

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

ich kann nur hinzufügen, Felder für Urtyp properites, aber nicht für Objekte zu erstellen.

Ich würde wirklich jede Hilfe schätzen!

+0

Verweisen Sie die Antworten [hier] (http://stackoverflow.com/questions/29161481/post-a-form-array-without-successful/29161796#29161796) und [hier] (http://stackoverflow.com/questions/28019793/submit-same-partially-view-called-multiple-mal-data-to-controller/28081308 # 28081308). Beachten Sie, dass Sie 'BeginCollectionItem' nicht für verschachtelte Sammlungen verwenden können. –

+0

Und für ein Arbeitsbeispiel zum dynamischen Erstellen verschachtelter Sammlungen, siehe [diese DotNetFiddle] (https://dotnetfiddle.net/wqE6Rb) –

Antwort

2

Ich denke, dass Sie einen üblichen Standard <input/> benötigen, den Sie von HTML5 wissen sollten. Wenn ich Sie richtig verstanden habe, möchten Sie die Daten von der Ansicht an den Controller übergeben. Jetzt sollten Sie eine Schaltfläche in dem von Ihnen erstellten Formular benötigen. Sie müssen/sollten einen Controller aufrufen, indem Sie die Modelldaten aus der Ansicht an den Controller übergeben. @Html.ActionLink() ist ein Razor-Helfer für <Input>

So etwas wie dies in der Form sollte den Trick kann tun:

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

Die Logik hinter dem Zeug passieren sollte im Controller. Ich hoffe, das kann dir helfen.

+0

Hallo H. Senkaya Ja, ich habe bereits eine Übermitteln Sie die Schaltfläche und die Logik befindet sich im Controller. Ich frage mich jedoch, wie ich eine neue Liste erstellen und der Liste Elemente aus der Ansicht hinzufügen kann. Wenn ich also auf "Senden" klicke, werden die Daten angezeigt. –

2

Ich habe ein Projekt zu Ihrem Szenario gemacht. Ich konnte jedoch keine Rasiererlösung finden. Also habe ich das SheepIt jquery Plugin verwendet, um Felder dynamisch hinzuzufügen.

https://github.com/mdelrosso/sheepit

Stellen Sie sicher, Sie ID und Name Muster kleben, die asp mvc versteht.

<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>

hoffe, das hilft!

+0

Hallo Vish J Nun, ich habe tatsächlich eine Lösung gefunden, indem Sie Elemente in die Liste mit reinem Javascript und kleben an MVC Benennungsmuster. Dies wird jedoch zu lange dauern, wenn Sie große komplexe verschachtelte Objekte haben. –

7

Hierfür können Sie verwenden Html.BeginCollectionItemhttps://www.nuget.org/packages/BeginCollectionItem/

Was können Sie tun, ist eine Ansicht für das Hauptformular haben und Übergeben Sie das Parent Modell, um es als dies die Eltern vertreten wird, dann müssen Sie ein Zeile für ein Kind, können Sie dies anrufen ChildRow.cshtml

Also für das Parent erstellen wir Create.cshtml Ansicht, die wir das Parent-Modell übergeben werden.

@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> 
    } 

Dann ist es das, was der ChildRow.cshtml aussehen wird, wird es ein Child Modell.

Hinweis: Sie müssen IsDeleted-Eigenschaft zum untergeordneten Modell hinzufügen, dies wird Ihnen in der Steuerung helfen, um zu sehen, ob Kind gelöscht wurde oder nicht.

@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> 
} 

Jetzt haben Sie eine Reihe bis zum Ende der Tabelle hinzuzufügen, wenn die Schaltfläche Add Child geklickt wird.

Dafür werden Sie eine neue Aktion im Controller erstellen:

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

Und dann fügen Sie diese jQuery zum Create.cshtml

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

dies wird ein neues Kind Zeile in die Tabelle anhängen

Auch Sie müssen die Zeile verstecken/deaktivieren, wenn Sie auf der gleichen Seite auch löschen möchten, für die Sie diese jQuery hinzufügen können:

$('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); 
    } 

}); 

Dann, wenn Sie zurück zum Controller POST, sehen Sie die Liste der Kinder im Modell.

[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); 
} 

Sie müssen etwas Ähnliches für die GrandChildren tun.

+1

Wow, das hat wirklich funktioniert, danke für dein Beispiel jetzt habe ich ein besseres Verständnis, wie man Html.BeginCollectionItem verwendet. Als Antwort markiert :) –