How to add an item to a list in a ViewModel using Razor and .NET Core?

与世无争的帅哥 提交于 2020-06-09 10:28:27

问题


So here's my situation.

Let's say I have a view called TheView.cshtml. TheView.cshtml has a ViewModel called TheViewModel.cs. In TheViewModel.cs, resides a List of an object (TheObject) called TheObjectList.

I have an editor template for TheObject called TheObject.cshtml. Using this editor template, I can simply display all of the items in the TheObjectList with @Html.EditorFor(model => model.TheObjectList).

However, now I want to dynamically add objects to this list. I have a AJAX function which calls a simple partial view to give the user a blank row to add a new "TheObject", however, any new TheObject I add dynamically is not considered part of the original TheObjectList.

This is because each item in the original TheObjectList is created with a certain prefix based on its index in the original list, whereas each new dynamic TheObject is created without a prefix, thus Razor does not see it as part of the list.

Is there a way around this?

TheView.cshtml

@model Models.ViewModels.TheViewModel

<table id="Table">
    <tbody>
        @Html.EditorFor(m => m.TheObjectList);
    </tbody>
</table>

<button id="AddObject" type="button" class="btn btn-primary">Add Object</button>

TheViewModel.cs

public class TheViewModel
{
    public List<TheObject> TheObjectList { get; set; }
}

AddObject Controller Method

public IActionResult AddObject()
{
   return PartialView("_EmptyRow", new TheObject());
}

AJAX Method to Add Object

$('#AddObject').click(function () {
    $.ajax({
        url: 'AddObject',
        cache: false,
        success: function (data) {
            $('#Table > tbody').append(data);
        },
        error: function (a, b, c) {
            alert(a + " " + b + " " + c);
        }
     });
});

回答1:


You basically needs to generate/return markup which looks same as what the editor template generates for your form fields except for the element index . You need to pass the index from client side which will be a part of the form field name.

Let's assume your editor template looks like below and your TheObject has a GroupName property

@model TheObject
<div>
    @Html.HiddenFor(x => x.GroupName)
    @Html.TextBoxFor(s=>s.GroupName,new {@class="thingRow"})
</div>

Now when you render your page with your current code, Editor template will generate input fields like this

<input class="thingRow" id="TheObjectList_0__GroupName" 
                           name="TheObjectList[0].GroupName" type="text" value="Something">

where 0 will be replaced with the index of the items in your TheObjectList collection.

Now let's say you already have 5 items in the collection, So when user clicks add button, you want to generate markup like above except 0 will be replaced with 5(for the sixth item). So let's update the ajax call to include the current number of items.

$('#AddObject').click(function () {
    var i = $(".thingRow").length;
    $.ajax({
        url: 'AddObject?index=' + i,
        success: function (data) {
            $('#Table > tbody').append(data);
        },
        error: function (a, b, c) {
            console.log(a, b, c);
        }
    });
});

That means, we need to accept the index value in our action method. Since we need to pass this index value from action method to our view to build the input field name value, I added a property to your class called Index

public ActionResult AddObject(int index)
{
    return PartialView("_EmptyRow", new TheObject { Index = index});
}

Now in your _EmptyRow partial view,

@model TheObject
<input id="TheObjectList_@(Model.Index)__GroupName"class="thingRow" 
             name="TheObjectList[@(Model.Index)].GroupName"  type="text" value=""/>

Now when you submit the form, model binding will work for these dynamically added items, assuming you have your Table inside a form.

@model TheViewModel
@using (Html.BeginForm())
{   
    <table id="Table">
        <tbody>
            @Html.EditorFor(m => m.TheObjectList);
        </tbody>
    </table>
    <button id="AddObject" type="button" class="btn btn-primary">Add Object</button>
    <button type="submit" class="btn btn-primary">Save</button>
}


来源:https://stackoverflow.com/questions/36317362/how-to-add-an-item-to-a-list-in-a-viewmodel-using-razor-and-net-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!