Home > Software engineering >  EF Core ASP.NET MVC include details and index in one view one-to-many
EF Core ASP.NET MVC include details and index in one view one-to-many

Time:10-17

EF Core ASP.NET MVC include details and index in one view one-to-many

I have a todo table with a one-to-many relationship to a steps table. There are many steps for each todo. The Index view lists all the todos, and the Details view shows one todo with its many steps in a table below it. What I would like is to have a view that shows all the todos listed with all of its steps under each. I plan to have an accordion to expand/collapse the steps for each todo in the list. Any help on how to do this would be greatly appreciated.

controller

public IActionResult Index()
{

    List<TodoList> todolists;
    todolists = _context.TodoLists.ToList();
    return View(todolists);
}

public IActionResult Details(int id)
{
    TodoList todolist = _context.TodoLists
        .Include(e => e.Steps)
        .Where(a => a.Id == id).FirstOrDefault();
     return View(todolist);
}

Details view

<form asp-action="Details" id="TodoForm">
    <div asp-validation-summary="ModelOnly" ></div>
    <div >
        <label asp-for="Name" ></label>
        <input asp-for="Name"  disabled />
    </div>
    <div >
        <label asp-for="Description" ></label>
        <input asp-for="Description"  disabled />
    </div>
    <div >
    </div>
     <div >
        <table  id="StepTable">
            <thead>
                <tr>
                    <th>Priority</th>
                    <th>Name</th>
                    <th style="width:75px;">
                    </th>
                </tr>
            </thead>
            <tbody>
                @for (int i = 0; i < Model.Steps.Count; i  )
                {
                    <tr>
                        <td>
                            <input asp-for="@Model.Steps[i].Priority"  disabled />
                        </td>
                        <td>
                            <input asp-for="@Model.Steps[i].Name"  disabled />
                        </td>
                        <td style="width:60px;">
                        </td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
    <input type="hidden" id="hdnLastIndex" value="0" />
</form>

Index view

<table >
<thead>
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Description)
        </th>
        <th></th>
    </tr>
</thead>
<tbody>
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Description)
        </td>
        <td>
            <a asp-action="Edit" asp-route-id="@item.Id" ><i ></i>&nbsp;Edit</a>
            <a asp-action="Details" asp-route-id="@item.Id" ><i ></i>&nbsp; Details </a>
            <a asp-action="Delete" asp-route-id="@item.Id" ><i ></i>&nbsp;Delete</a>
        </td>
    </tr>
}
</tbody>
</table>

CodePudding user response:

I suggest you can use Bootstrap Collapse.

Firstly be sure your project contains bootstrap.css and bootstrap.js.

Then,check the Bootstrap version. Bootstrap uses data-target/data-toggle before v5.0 and uses data-bs-target/data-bs-toggle for v5.0.

Here is a whole working demo:

Model

public class TodoList
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public List<Step> Steps { get; set; }
}
public class Step
{
    public int Id { get; set; }
    public string Priority { get; set; }
    public string Name { get; set; }
}

View

@model IEnumerable<TodoList>

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table >
    <thead>
        <tr>
            <th></th>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Description)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
    @{
        int i = 0;
    }
    @foreach (var item in Model) {
        <tr>
            <td>
                <button type="button"  
                                        data-bs-toggle="collapse" data-bs-target="#step_@i"
                                        aria-expanded="false" aria-controls="step_@i">   </button>
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Description)
            </td>

            <td>
                <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
                <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
            </td>
         </tr>
        <tr id="step_@i" >
        @for (int j = 0; j < item.Steps.Count; j  )
        {
            <td>
                Priority:<input asp-for="@item.Steps[j].Priority"  disabled />
                <br/>
                Name:<input asp-for="@item.Steps[j].Name"  disabled />
            </td>
        }
        </tr>
         i  ;
    }
    </tbody>
</table>

Add Bootstrap.css and Bootstrap.js in _Layout.cshtml

<head>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
</head>
 <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>

Controller

public class TodoListsController : Controller
{
    private readonly MvcProjContext _context;

    public TodoListsController(MvcProjContext context)
    {
        _context = context;
    }

    // GET: TodoLists
    public async Task<IActionResult> Index()
    {
          return View(await _context.TodoLists.Include(a=>a.Steps).ToListAsync());
    }
}
  • Related