Search code examples
c#asp.net-coremodel-view-controllerrazor

How to add to a list in a view model with MVC within the Index page


I'm trying to add to a list in my view model within the index.cshtml and without the need for a partial or a seperate view.

I have a Telesales view in MVC. The view model for this is simply two lists - one for consultants and one for operatives.

public class TelesalesViewModel
{
    public List<TelesalesOperativeViewModel> Operatives { get; set; }
    public List<TelesalesConsultantViewModel> Consultants { get; set; }
}

Each of these lists do have their own view models for the purposes of displaying them which are below:

public class TelesalesConsultantViewModel
{
    public Guid ConsultantId { get; set; }
    public string Name { get; set; }
}

public class TelesalesOperativeViewModel
{
    public Guid OperativeId { get; set; }
    public string Name { get; set; }
}

In the view I list these directly for the TelesalesViewModel:

@model TelesalesViewModel


<h3>Telesales Data</h3>

<h4>Operatives</h4>

<form class="form-horizontal" enctype="multipart/form-data" id="AddOperativeForm" method="post" action="/Telesales/AddNewOperative">
    <label>Name</label>
    @Html.EditorFor(m => m.Operatives.Name, new { htmlAttributes = new { @class = "form-control" } });

    <button type="submit" class="btn btn-primary">Add Operative</button>
</form>
@if (Model.Operatives.Count > 0)
{
    <table class="table table-striped">
            <thead>
                <tr>
                    <th>Name</th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
                @foreach (var item in Model.Operatives) {
                    <tr>
                        <td>@item.Name</td>
                        <td><a class="btn btn-secondary" href="@Url.Action("DeleteOperative", "TelesalesController", new { operativeId = item.OperativeId })">Delete</a></td>
                    </tr>
                }
            </tbody>
    </table>
} 

<h4>Consultants</h4>

<form class="form-horizontal" enctype="multipart/form-data" id="AddConsultantForm" method="post" action="/Telesales/AddNewConsultant">
    <label>Name</label>
    @Html.EditorFor(m => m.Consultants.Name, new { htmlAttributes = new { @class = "form-control" } });

    <button type="submit" class="btn btn-primary">Add Consultant</button>
</form>
@if (Model.Consultants.Count > 0)
{
    <table class="table table-striped">
            <thead>
                <tr>
                    <th>Name</th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
                @foreach (var item in Model.Consultants) {
                    <tr>
                        <td>@item.Name</td>
                        <td><a class="btn btn-secondary" href="@Url.Action("DeleteConsultant", "TelesalesController", new { operativeId = item.ConsultantId })">Delete</a></td>
                    </tr>
                }
            </tbody>
    </table>
}

For the top form I want to use the input to enter a name and add this to the operatives list and the bottom form to enter a name and this to the consultants list. Both hook up to the relative methods in the controller, that's all fine. It's when I try to map the editor to the right property within the list, because although the TelesalesViewModel contains the lists, it doesn't contain individual properties for the objects in the list.

Is there a way I can do this? Like maybe use the HTML input to pass a parameter for the name to the coressponding 'AddNew...' method? I've hunted around but everything is eitherr just saying to use AJAX (which is fine it's just that I can't find an example of the actual code anywhere) or creating a new/partial view.

I feel like there's something really simple to do this that I'm missing?


Solution

  • You can use ajax to pass name to action,and save the model to db,then return the added model,and add html to tbody. view:

    @model TelesalesViewModel
    
    
    <h3>Telesales Data</h3>
    
    <h4>Operatives</h4>
    
    <form class="form-horizontal" enctype="multipart/form-data" id="AddOperativeForm" method="post" action="/Telesales/AddNewOperative">
        <label>Name</label>
         <input class="form-control" id="OperativeName" name="OperativeName" />
        <input type="button" onclick="AddOperative()" class="btn btn-primary" value="Add Operative" />
    </form>
    @if (Model.Operatives.Count > 0)
    {
        <table id="OperativesTable" class="table table-striped">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var item in Model.Operatives) {
                        <tr>
                            <td>@item.Name</td>
                            <td><a class="btn btn-secondary" href="@Url.Action("DeleteOperative", "TelesalesController", new { operativeId = item.OperativeId })">Delete</a></td>
                        </tr>
                    }
                </tbody>
        </table>
    } 
    
    <h4>Consultants</h4>
    
    <form class="form-horizontal" enctype="multipart/form-data" id="AddConsultantForm" method="post" action="/Telesales/AddNewConsultant">
        <label>Name</label>
       <input class="form-control" id="ConsultantName" name="ConsultantName" />
        <input type="button" onclick="AddConsultant()" class="btn btn-primary" value="Add Consultant" />
    </form>
    @if (Model.Consultants.Count > 0)
    {
        <table id="ConsultantsTable" class="table table-striped">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var item in Model.Consultants) {
                        <tr>
                            <td>@item.Name</td>
                            <td><a class="btn btn-secondary" href="@Url.Action("DeleteConsultant", "TelesalesController", new { operativeId = item.ConsultantId })">Delete</a></td>
                        </tr>
                    }
                </tbody>
        </table>
    }
    

    js:

    <script>
            function AddOperative() {
                $.ajax({
                    type: "POST",
                    url: "/Telesales/AddNewOperative",
                    data: { "OperativeName": $("#OperativeName").val() },
                    success: function (data) {
    
                        var html = "<tr><td>" + data.name + "</td><td><a class='btn btn-secondary' href='Telesales/DeleteOperative?operativeId=" + data.operativeId + "'>Delete</a></td></tr>";
                        $("#OperativesTable tbody")[0].innerHTML += html;
                    }
                });
            }
            function AddConsultant() {
                $.ajax({
                    type: "POST",
                    url: "/Telesales/AddNewConsultant",
                    data: { "ConsultantName": $("#ConsultantName").val() },
                    success: function (data) {
    
                        var html = "<tr><td>" + data.name + "</td><td><a class='btn btn-secondary' href='Telesales/DeleteOperative?operativeId=" + data.consultantId + "'>Delete</a></td></tr>";
                        $("#ConsultantsTable tbody")[0].innerHTML += html;
                    }
                });
            }
        </script>
    

    TelesalesController:

    public TelesalesOperativeViewModel AddNewOperative(string OperativeName)
            {
                //save data ans return TelesalesOperativeViewModel here
            }
            public TelesalesConsultantViewModel AddNewConsultant(string ConsultantName)
            {
               //save data ans return TelesalesConsultantViewModel here
            }