Erik Sellberg
Erik Sellberg

Reputation: 511

How to use PaginatedList with ViewModel using MVC

I am trying to find a solution for creating a PaginatedList with a ViewModel.

Tutorial (using only an ordinary model)

https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/sort-filter-page?view=aspnetcore-2.1

Similar problem

How do I paginate through a ViewModel in MVC CORE?

MVC/Entity framework core using ViewModel with paging

My Code

Controller

public async Task<IActionResult> Index(string sortOrder, string currentFilter, string searchString, int? page)
        {
            ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";

            if (searchString != null)
            {
                page = 1;
            }

            else
            {
                searchString = currentFilter;
            }

            ViewData["CurrentFilter"] = searchString;

            var palletAccounts = from p in _context.PalletAccount
                select p;

            if (!String.IsNullOrEmpty(searchString))
            {
                palletAccounts = palletAccounts.Where(s => s.AccountName.Contains(searchString));
            }

            switch (sortOrder)
            {
                case "name_desc":
                    palletAccounts = palletAccounts.OrderByDescending(s => s.AccountName);
                    break;
                default:
                    palletAccounts = palletAccounts.OrderBy(s => s.AccountName);
                    break;
            }

            var palletAccountSelectListItems = (from p in _context.PalletAccount
                select p.PalletGroupName).Distinct().Select(a => new SelectListItem(a,a));

            int pageSize = 10;

            return View(new PalletAccountViewModel { PalletAccounts = await PaginatedList<PalletAccount>.CreateAsync(palletAccounts.AsNoTracking(), page ?? 1, pageSize), GroupNames = await palletAccountSelectListItems.ToListAsync()});
        }

ModelView

 public class PalletAccountViewModel
    {
        public PalletAccount PalletAccount { get; set; }
        public IEnumerable<PalletAccount> PalletAccounts { get; set; }
        public IEnumerable<SelectListItem> GroupNames { get; set; }
    }

Index-page (razor)

   @model PaginatedList<PalletPortal.Models.ViewModels.PalletAccountViewModel> <--if I use the model without PaginatedList it works fine (except the paging obviously).


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

<div class="space"></div>

<section class="main-section">
    <table class="table" id="tableCenter">
        <thead>
            <tr>
                <th>
                    <a asp-action="Index" asp-route-sortOrder="@ViewData["NameSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">@Html.DisplayNameFor(model => model.PalletAccount.AccountName)</a>
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.PalletAccount.PalletGroupName)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.PalletAccount.PalletAccountType)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.PalletAccount.IsActive)
                </th>
                <th> <button class="button" id="myBtn"><span>Skapa pallkonto </span></button></th>
            </tr>
        </thead>
        <tbody>

            @foreach (var item in Model.PalletAccounts)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.AccountName)
                    </td>
                    <td>
                        @Html.DisplayFor(modelitem => item.PalletGroupName)
                    </td>
                    <td>
                        @Html.DisplayFor(modelitem => item.PalletAccountType)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.IsActive, new { @class = "checkbox" })
                    </td>
                    <td>
                        <a asp-action="Delete" asp-route-id="@item.ID"><button class="button" style="vertical-align: middle"><span>Radera </span></button></a>
                        <a asp-action="Edit" asp-route-id="@item.ID"><button class="button" style="vertical-align: middle"><span>Redigera </span></button></a>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    @{
        var prevDisabled = !Model.HasPreviousPage ? "disabled" : "";
        var nextDisabled = !Model.HasNextPage ? "disabled" : "";
    }

    <a asp-action="Index"
       asp-route-sortOrder="@ViewData["CurrentSort"]"
       asp-route-page="@(Model.PageIndex - 1)"
       asp-route-currentFilter="@ViewData["CurrentFilter"]"
       class="btn btn-default @prevDisabled">
        Previous
    </a>
    <a asp-action="Index"
       asp-route-sortOrder="@ViewData["CurrentSort"]"
       asp-route-page="@(Model.PageIndex + 1)"
       asp-route-currentFilter="@ViewData["CurrentFilter"]"
       class="btn btn-default @nextDisabled">
        Next
    </a>

I cannot access my models in the Index-page (PalletAccount and palletAccounts).

For example: model => model.PalletAccount.AccountName Can someone point me in the right direction?

Thanks in advance.

Upvotes: 1

Views: 2754

Answers (1)

user3559349
user3559349

Reputation:

Your controller is passing an instance of PalletAccountViewModel to the view, therefore you need to change the model in the view to

@model PalletAccountViewModel

Then since you want paginate the PalletAccounts property, you need to change the view model to

public class PalletAccountViewModel
{
    public PalletAccount PalletAccount { get; set; }
    public PaginatedList<PalletAccount> PalletAccounts { get; set; } // change
    public IEnumerable<SelectListItem> GroupNames { get; set; }
}

and in the view

@{
    var prevDisabled = !Model.PalletAccounts.HasPreviousPage ? "disabled" : "";
    var nextDisabled = !Model.PalletAccounts.HasNextPage ? "disabled" : "";
}

Upvotes: 1

Related Questions