【JQuery】函式庫-從0到87實作Select2 之一

  • 644
  • 0
  • 2020-11-30

從0到87實作Select2

1.建立MVC專案

2.建立Controller

3.下載Nuget必要套件

4.BundleConfig與_Layout.cshtml設定

5.Controller產生下拉式選單

6.透過ViewBag將Controller產生的下拉式選單傳給Index頁面

7.Index頁面呼叫select2()方法

【前置作業】

================= 建立SQL Table與資料 Start =================

USE [SideProject]
GO
/****** Object:  Table [dbo].[Books]    Script Date: 2020/11/27 20:35:48 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Books](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NULL,
    [Author] [nvarchar](max) NULL,
    [Category] [nvarchar](20) NULL,
 CONSTRAINT [PK_dbo.Books] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Books] ON 
GO
INSERT [dbo].[Books] ([Id], [Name], [Author], [Category]) VALUES (1, N'三體', N'劉慈欣', N'科幻')
GO
INSERT [dbo].[Books] ([Id], [Name], [Author], [Category]) VALUES (2, N'旋元佑文法', N'旋元佑', N'英文')
GO
INSERT [dbo].[Books] ([Id], [Name], [Author], [Category]) VALUES (3, N'風之影', N'卡洛斯·魯依斯·薩豐', N'文學')
GO
INSERT [dbo].[Books] ([Id], [Name], [Author], [Category]) VALUES (4, N'時間迴旋', N'羅伯特·查爾斯·威爾森', N'文學')
GO
INSERT [dbo].[Books] ([Id], [Name], [Author], [Category]) VALUES (6, N'殺鬼', N'甘耀明', N'台灣文學')
GO
INSERT [dbo].[Books] ([Id], [Name], [Author], [Category]) VALUES (7, N'笑傲江湖', N'金庸', N'武俠')
GO
SET IDENTITY_INSERT [dbo].[Books] OFF
GO

================= 建立SQL Table與資料 End =================

================= 建立MVC專案 Start =================

【建置專案】

                    ================= 下載相關Nuget套件 Start =================

 

一、Dapper,本篇文章使用Dapper獲取資料庫資料

二、select2 本篇主角

                    ================= 下載相關Nuget套件 End =================

                    ================= 建立必要的Model Start =================

【BOOKS】 用以承接透過Dapper從SQL取得的資料    

public class BOOKS
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public string Author { get; set; }

        public Categories Category { get; set; }
    }

 

【Categories 】 string其實也可以,只是我順便練習Enum的使用

namespace Select2_Demo.Models //namespace 從namespace Select2_Demo.Models.Enum改為namespace Select2_Demo.Models 就不用特地using
{
    public enum Categories
    {
        科幻 = 1,

        英文 = 2,

        文學 = 3,

        台灣文學 = 4,

        武俠 = 5
    }
}

    

                    ================= 建立必要的Model End =================

【Controller】

建立兩個Controller與對應的index View,分別為NormalController 與 AjaxController

NormalController用以實作、呈現一般的Select2特性

AjaxController用以實作、呈現Select2與Ajax相關的特性

View用來呈現實作後的效果

AjaxController建立完成後一樣長這樣

【NormalController】

using Dapper;                             //引用Dapper 詳見private List<BOOKS> GetBooksList()
using Select2_Demo.Models;    //引用Model
using System.Data.SqlClient;    //引用 System.Data.SqlClient 與SQL連線相關

                    =================【NormalController】 Dapper 獲取資料  Start =================

step1 建立連線字串 

        //設定連線字串供dapper使用 

        註:我的DB名字叫做SideProject  實際連線的字串因人而異,需稍做修改
        string cnString = "Data Source=.\\ SQLExpress;Initial Catalog=SideProject;Integrated Security=True";
 

step2 建立private方法 private List<BOOKS> GetBooksList()

建立與SQL間的聯繫相信讀者不會感到陌生,但如果要​使用第27行的 select * from Books 

就必須引用Dapper了,這也是Dapper強大的地方,但本篇並非介紹Dapper,因此暫不贅述。

step3 Index呼叫private List<BOOKS> GetBooksList() => 執行專案,透過中斷點的建立來檢視資料

            var allBooks = GetBooksList();

註:快速監看式熱鍵  Ctrl+Alt+W 再按數字鍵1

從快速監看式中,就可以看到我們透過Dapper從SQL中取得了稍早建立的資料,是不是很棒棒阿

所以說Dapper真的很好用呢(這不是本篇重點)

                    =================【NormalController】 Dapper 獲取資料  End =================

                    =================【NormalController】建立下拉式選單 Start =================

using Linq;

public ActionResult Index()
        {
            var allBooks = GetBooksList();
            var distinctCategories = allBooks.Select(x => x.Category).Distinct();

            List<SelectListItem> selectListItems = new List<SelectListItem>();

            var specificFieldsOfBook = allBooks.Select(x => new
            {
                id = x.Id,
                text = x.Author + "-" + x.Name,
                Category = x.Category.ToString()
            });

            foreach (var eachSpecificFieldsOfBook in specificFieldsOfBook)
            {
                SelectListItem selectListItem = new SelectListItem()
                {
                    Text = eachSpecificFieldsOfBook.text,
                    Value = eachSpecificFieldsOfBook.id.ToString(),
                };

                //預設selected與disabled選項
                if (eachSpecificFieldsOfBook.text.Contains("風之影")) selectListItem.Disabled = true;
                if (eachSpecificFieldsOfBook.text.Contains("時間迴旋")) selectListItem.Selected = true;

                selectListItems.Add(selectListItem);
            }

            ViewBag.AllBooks = selectListItems;
            ViewBag.AllCategories = new SelectList(distinctCategories);

            return View();
        }

18行 將所有書籍的Category取出並且Distinct => 取得所有書籍類別

22行 的型別是IEnumerable 我希望把Books挑出來的特定欄位做成SelectList的value(Post時Controller接到的值)與text(index畫面上呈現的文字)

         順帶一提,變數的命名需要能夠讓人一眼看出這個變數在幹嘛,或是其代表的意義為何,這點我也還在持續努力

24行 (重點) id 為select2指定的名稱 其代表的意義等同於value

25行 (重點) text為select2指定的名稱 其代表的意義等同於text

29行 - 42行 於後端產生下拉式選單的其中一種方法

                   specificFieldsOfBook的資料結構如下圖

38,39行 順帶一提,下拉式選單丟到前端時,若未指定預設選項、或者做其他處理,則會將第一筆資料設為預設呈現的資料

              這邊順便提供預設選取 及 Disabled(不給選)的其中一種設定方法

44,45行 此篇文章透過ViewBag的方式將資料包在ViewBag傳遞給Index前端頁面

                    =================【NormalController】建立下拉式選單 End =================

                    =================【NormalController - Index】下拉式選單 Start =================

NormalController -【Index頁面】

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<string>取得所有書籍+關鍵字搜索</string>
@Html.DropDownList("NormalSelectAllBooks", (IEnumerable<SelectListItem>)ViewBag.AllBooks, null, new { @class = "form-control", @id = "NormalSelectAllBooks" })
<string style="color:red">預設selected與disabled選項 </string>
<br /><br />


@section Scripts
{
    <script type="text/javascript">
        $(document).ready(function () {
            $("#NormalSelectAllBooks").select2();
                })
    </script>
}
 

6行 承接ViewBag轉為下拉式選單的方法,注意id為@id = "NormalSelectAllBooks"

15行,JQuery ID Selector  呼叫.select2()方法進行初始化

下拉式選單出來了,預設選取和Disabled的選項也如預期,但484有哪裡怪怪的,所以我說那個select2呢?  打開F12 看Console的提示 會發現如下錯誤

                    =================【NormalController - Index】下拉式選單 End =================

                    =================【BundleConfig】Bundle設定 Start =================

位置 專案/App_Start/BundleConfig.cs

using System.Web;
using System.Web.Optimization;

namespace Select2_Demo
{
    public class BundleConfig
    {
        // 如需統合的詳細資訊,請瀏覽 https://go.microsoft.com/fwlink/?LinkId=301862
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.validate*"));

            bundles.Add(new ScriptBundle("~/bundles/select2").Include(
             "~/Scripts/select2.js"));

            // 使用開發版本的 Modernizr 進行開發並學習。然後,當您
            // 準備好可進行生產時,請使用 https://modernizr.com 的建置工具,只挑選您需要的測試。
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                      "~/Scripts/bootstrap.js"));

            bundles.Add(new StyleBundle("~/Content/css").Include(
                      "~/Content/bootstrap.css",
                      "~/Content/site.css"));

            bundles.Add(new StyleBundle("~/Select2").Include(
             "~/Content/css/select2.css"));

        }
    }
}
 

在Nuget下載完select2相關的套件後,其實還有兩個必須做的步驟,第一就是在Bundle中添加紅字部分的程式碼

關於Bundle其實也是一個很重要的概念,但在此就先不贅述。

                    =================【BundleConfig】Bundle設定 End =================

                    =================【_Layout.cshtml】共用頁面設定 Start =================

位置 專案/Views/Shared/_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - 我的 ASP.NET 應用程式</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    @Styles.Render("~/select2")
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("應用程式名稱", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("首頁", "Index", "Home")</li>
                    <li>@Html.ActionLink("關於", "About", "Home")</li>
                    <li>@Html.ActionLink("連絡人", "Contact", "Home")</li>
                </ul>
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - 我的 ASP.NET 應用程式</p>
        </footer>
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @Scripts.Render("~/bundles/select2")

    @RenderSection("scripts", required: false)
</body>
</html>
 

在Nuget下載完select2相關的套件後,其實還有兩個必須做的步驟,第二就是在_Layout.cshtml (也就是Index頁面上引用的畫面) 中添加紅字部分的程式碼

關於_Layout.cshtml其實也是一個很重要的概念,但在此就先不贅述。

                    =================【_Layout.cshtml】共用頁面設定 End =================

NormalController -【Index頁面】

設定完BundleConfig與_Layout之後 再次執行專案,回到Index頁面

可以看到Console沒有呈現任何錯誤,下拉式選單中也多出了搜尋框

實際上使用搜尋功能也能夠正確的查找存在的書籍,與不存在的書籍

                    =================【NormalController - Index】下拉式選單 End =================

================= 建立MVC專案 End =================