iT邦幫忙

2021 iThome 鐵人賽

DAY 12
0
Modern Web

從實作學習ASP.NET Core - 30天的購物網站系列 第 12

【從實作學習ASP.NET Core】Day12 | 後台 | 資料篩選與分頁

前面我們已經完成了 Create 和 Details , 今天就來實作 List 頁面


List 頁面

顯示

前端頁面我們隨便挑幾項出來排版,讓庫存大於 0 的商品顯示在庫:

<td>
    @if (item.Stock > 0)
    {
        @Html.Raw("<span class=" + "\" badge bg-success text-white \"" + ">在庫中</span>")
    }
    else
    {
        @Html.Raw("<span class=" + "\" badge bg-warning text-dark \"" + ">缺貨中</span>")
    }
</td>

篩選資料

還記得如何從網址傳數值給 Controller 嗎,就是在網址後面加上?來添加參數
忘記的可以回去看看前面的文章:Day03 | Controller 控制器

所以我們調整Index()的參數,讓它能用 searchString 的值來搜尋資料庫

public async Task<IActionResult> Index(string searchString)
{
    var result = from m in _context.Product select m;
    
    if (!string.IsNullOrEmpty(searchString))
    {
        result = result.Where(s => s.Name.Contains(searchString));
    }
    
    return View(result.Include(p => p.Category).ToListAsync());
}

測試一下,在網址後面傳值?searchString=Nintendo,果然選出我們要的資料

但是在實務上不可能讓使用者每次搜尋都要改網址,這樣太不直觀了
所以還需要建一個input欄位來讀取searchString,在前端Index.cshtml加上input欄位

<form asp-action="Index" class="col-4 ">
    <div class="input-group input-group-sm ">
        <input class="form-control" type="text" placeholder="Name" name="searchString" />
        <input class="btn btn-sm btn-primary" type="submit" value="Search" />
    </div>
</form>

分頁

要達成分頁,可以建立一個 PaginatedList 來繼承一般 List

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace OnlineShopCMS.Models
{
    public class PaginatedList<T> : List<T>
    {
        public int PageIndex { get; private set; }
        public int TotalPages { get; private set; }

        public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
        {
            PageIndex = pageIndex;
            TotalPages = (int)Math.Ceiling(count / (double)pageSize);

            this.AddRange(items);
        }

        public bool HasPreviousPage
        {
            get
            {
                return (PageIndex > 1);
            }
        }

        public bool HasNextPage
        {
            get
            {
                return (PageIndex < TotalPages);
            }
        }

        public static async Task<PaginatedList<T>> CreateAsync(
            IQueryable<T> source, int pageIndex, int pageSize)
        {
            var count = await source.CountAsync();
            var items = 
                await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
            return new PaginatedList<T>(items, count, pageIndex, pageSize);
        }
    }
}

接著調整 Index() 成下面這個樣子

public async Task<IActionResult> Index(string searchString, string currentFilter, int? pageNumber)
{
    if (searchString != null)
    {
        pageNumber = 1;
    }
    else
    {
        searchString = currentFilter;
    }
    ViewData["CurrentFilter"] = searchString;  // 儲存當前搜尋狀態

    var result = from m in _context.Product select m;

    if (!string.IsNullOrEmpty(searchString))
    {
        result = result.Where(s => s.Name.Contains(searchString));
    }

    int pageSize = 5;  //一頁顯示幾項
    return View(await PaginatedList<Product>.CreateAsync(
        result.Include(p => p.Category).AsNoTracking(), pageNumber ?? 1, pageSize)
    );
}

最後在前端 Index.cshtml 加上上下頁的按鈕

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

<div class="d-flex justify-content-center">
    <a asp-action="Index" 
        asp-route-pageNumber="@(Model.PageIndex - 1)" 
        asp-route-currentFilter="@ViewData["CurrentFilter"]" 
        class="btn btn-default @prevDisabled">Previous
    </a>
    <a asp-action="Index" 
        asp-route-pageNumber="@(Model.PageIndex + 1)" 
        asp-route-currentFilter="@ViewData["CurrentFilter"]" 
        class="btn btn-default @nextDisabled">Next
    </a>
</div>

看一下成果


上一篇
【從實作學習ASP.NET Core】Day11 | 後台 | 詳細資料與 ViewModel
下一篇
【從實作學習ASP.NET Core】Day13 | 後台 | 編輯與刪除
系列文
從實作學習ASP.NET Core - 30天的購物網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
緯大啊緯大人
iT邦研究生 1 級 ‧ 2021-09-27 08:52:26

你還自幹分頁,我已被DataTable屈服
/images/emoticon/emoticon01.gif

Yeh iT邦新手 4 級 ‧ 2021-09-27 19:26:58 檢舉

對欸!都忘記可以用DataTable了 xD

我要留言

立即登入留言