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

  • 644
  • 0

從0到87實作Select2

下拉式選單的87種變化

  ================= 取得書籍類別+關鍵字搜索(單選與多選) Start =================

【NormalController】

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

            ViewBag.AllCategories = new SelectList(distinctCategories);

            return View();
        }

        [HttpPost]
        public ActionResult Index(string NormalSelect, string[] MultiSelect)
        {

            return View();
        }

NormalController -【Index】

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

@using (Html.BeginForm())
{
    <string>取得書籍類別+關鍵字搜索</string>
    @Html.DropDownList("NormalSelect", (IEnumerable<SelectListItem>)ViewBag.AllCategories, null, new { @class = "form-control", @id = "NormalSelect" })
    <string style="color:red">單選,會預設第一個選項為已選擇 </string>
    <br /><br />

    <string>取得書籍類別+關鍵字搜索(多選)</string>
    @Html.DropDownList("MultiSelect", (IEnumerable<SelectListItem>)ViewBag.AllCategories, null, new { @class = "form-control", @id = "MultiSelect", @multiple = "multiple", @style = "width:580px" })
    <string style="color:red">多選,不會預設選項 </string>
    <br /><br />

    <input type="submit" value="提交此頁面"/>
}


@section Scripts
{
    <script type="text/javascript">
        $(document).ready(function () {
            //========取得書籍類別+關鍵字搜索 Start========
            $("#NormalSelect").select2();  //單選,會預設第一個選項為已選擇

            $("#MultiSelect").select2({ //多選,不會預設選項
                placeholder: "@@Html.DDL(.., new {@@multiple = \"multiple\" })"
            });
            //========取得書籍類別+關鍵字搜索 End========
        })
    </script>
}
 

13行 若要讓下拉選單為多選,則需要添加@multiple="multiple"的屬性,此為其中一種添加的方式

 

29行 placeholder 即為浮水印的效果​

實際多選時,效果如下

提交此頁面,將值傳送到Controller

註:注意Controller接收的名稱與型別


  ================= 取得書籍類別+關鍵字搜索(單選與多選) End =================

 

  ================= 取得書籍類別+關鍵字搜索(多選-最多三項;最多輸入5個字元;最少輸入2個字元) Start =================

此效果只需關注Index頁面的改動

NormalController -【Index】

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

@using (Html.BeginForm())
{
    <string>取得書籍類別+關鍵字搜索(多選-最多三項)</string>
    @Html.DropDownList("MultiSelectLimit3", (IEnumerable<SelectListItem>)ViewBag.AllCategories, null, new { @class = "form-control", @id = "MultiSelectLimit3", @multiple = "multiple" })
    <br /><br />

    <string>取得書籍類別+關鍵字搜索(最多輸入5個字元)</string>
    @Html.DropDownList("MultiSelectMaximumInputLength5", (IEnumerable<SelectListItem>)ViewBag.AllCategories, null, new { @class = "form-control", @id = "MultiSelectMaximumInputLength5", @multiple = "multiple", @maximumInputLength = 5 })
    <br /><br />

    <string>取得書籍類別+關鍵字搜索(最少輸入2個字元)</string>
    @Html.DropDownList("MultiSelectMinimumInputLength2", (IEnumerable<SelectListItem>)ViewBag.AllCategories, null, new { @class = "form-control", @id = "MultiSelectMinimumInputLength2", @multiple = "multiple", @minimumInputLength = 2 })
    <br /><br />


    <input type="submit" value="提交此頁面" />
}


@section Scripts
{
    <script type="text/javascript">
        $(document).ready(function () {
            //========取得書籍類別+關鍵字搜索(多選-最多三項) Start========
            $("#MultiSelectLimit3").select2({
                maximumSelectionLength: 3,
                placeholder: "maximumSelectionLength : integer"
            });
            //========取得書籍類別+關鍵字搜索(多選-最多三項) End========

            //========取得書籍類別+關鍵字搜索(最多輸入5個字元) Start========
            $("#MultiSelectMaximumInputLength5").select2({
                maximumInputLength: 5,
                placeholder: "maximumInputLength : integer"
            });
            //========取得書籍類別+關鍵字搜索(最多輸入5個字元) End========

            //========取得書籍類別+關鍵字搜索(最少輸入2個字元) Start========
            $("#MultiSelectMinimumInputLength2").select2({
                minimumInputLength: 2,
                placeholder: "minimumInputLength : integer"
            });
            //========取得書籍類別+關鍵字搜索(最少輸入2個字元) End========
        })
    </script>
}

寫在@Html後 (12,16行) 或是在select2({})宣告(30,37,44行) 都是一樣的效果,擇一就行了。

實際上的效果如下圖

 

 

  ================= 新增空白選項作為預設;若不存在則新增一個選項Start =================

【NormalController】

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

            ViewBag.AllCategories = new SelectList(distinctCategories);

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

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


            return View();
        }

        [HttpPost]
        public ActionResult Index(string AddDefaultOption,string CreateIfNotExist)
        {

            return View();
        }

新增一個ViewBag

NormalController -【Index】

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

@using (Html.BeginForm())
{
    <string>新增空白選項作為預設</string>
    @Html.DropDownList("AddDefaultOption", (IEnumerable<SelectListItem>)ViewBag.AllBooksWithoutSelected, null, new { @class = "form-control", @id = "AddDefaultOption" })
    <br /><br />

    <string>若不存在則新增一個選項</string>
    @Html.DropDownList("CreateIfNotExist", (IEnumerable<SelectListItem>)ViewBag.AllBooksWithoutSelected, null, new { @class = "form-control", @id = "CreateIfNotExist" })
    <br /><br />

    <input type="submit" value="提交此頁面" />
}


@section Scripts
{
    <script type="text/javascript">
        $(document).ready(function () {
            //======== 新增空白選項作為預設 Start========
            var emptyOption = {
                id: -94,
                text: "新增的預設選項"
            };
            /*第三個建構子為-是否在html上加上selected 但僅止於selected
              必須和第四個建構子同時為true,才能讓新增的選項成為default selected*/
            var newOption = new Option(emptyOption.text, emptyOption.id, true, true);

            /* Select2 will listen for the change event on the <select> element that
             * it is attached to. When you make any external changes that need to
             * be reflected in Select2 (such as changing the value),
             * you should trigger this event.*/
            $("#AddDefaultOption").append(newOption).trigger('change'); // Notify any JS components that the value changed


            //======== 新增空白選項作為預設 End========

            //======== Create if not exists Start========
            //尋找「新增的預設選項」是否存在,不存在則新增
            var AnotherOption = {
                id: -87,
                text: "若不存在則新增的預設選項"
            };
            if ($("#CreateIfNotExist").find("option[value='" + AnotherOption.id + "']").length) {
                $('#CreateIfNotExist').val(AnotherOption.id).trigger('change');
            } else {
                var newOption = new Option(AnotherOption.text, AnotherOption.id, true, true);
                $('#CreateIfNotExist').append(newOption).trigger('change');
            }
            //======== Create if not exists End========
        })
    </script>
}

30行 new Option(建構子1,2,3,4) 1:Text ; 2:Value ; 3:是否在html上加上selected ; 4: 搭配3 可輸入false 按F12自行比較差別

36行 使用append將24-30行新增的空白選項,加入("#AddDefaultOption")中  任何對內容的改變都需要透過.trigger('change')來告訴JS重新render畫面

43-52行是差不多的概念,只差在多一個判別,先去找看看("#CreateIfNotExist")裡面有沒有AnotherOption這個選項,沒有則新增

實際結果如下圖

若直接按下提交 Controller會接到

    ================= 新增空白選項作為預設;若不存在則新增一個選項End =================

    ================= AllowClear Start =================

此效果僅需關注Index頁面

NormalController-【Index】

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

@using (Html.BeginForm())
{
    <string>選項AllowedClear</string>
    @Html.DropDownList("NormalSelectAllowedClear", (IEnumerable<SelectListItem>)ViewBag.AllCategories, null, new { @class = "form-control", @id = "NormalSelectAllowedClear" })
    <string style="color:red"> 有x符號可以清空該選項 就不用寫一個空白選項</string>
    <br /><br />

    <string>選項NotAllowedClear</string>
    @Html.DropDownList("MultiSelectNotAllowedClear", (IEnumerable<SelectListItem>)ViewBag.AllCategories, null, new { @class = "form-control", @id = "MultiSelectNotAllowedClear" })
    <br /><br />
    <input type="submit" value="提交此頁面" />
}


@section Scripts
{
    <script type="text/javascript">
        $(document).ready(function () {
            //========選項AllowClear Start========
            $("#NormalSelectAllowedClear").select2({
                placeholder: "allowClear : true",
                allowClear: true
            })
            //========選項AllowClear End========

            //========選項NotAllowClear Start========
            $("#MultiSelectNotAllowedClear").select2({
                placeholder: "allowClear : false",
                allowClear: false //預設為false
            })
            //========選項NotAllowClear End========
        })
    </script>
}

實際效果如下圖

補充一下好惹  如果post到Controller,接到的值會是

    ================= AllowClear End =================

    ================= 選擇後自動關閉;關閉時選擇反白選項 Start =================

此效果僅需關注Index頁面

NormalController-【Index】

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

@using (Html.BeginForm())
{
    <string>選擇後自動關閉選單(預設)</string>
    @Html.DropDownList("closeOnSelectTrue", (IEnumerable<SelectListItem>)ViewBag.AllCategories, null, new { @class = "form-control", @id = "closeOnSelectTrue", @multiple = "multiple" })
    <br /><br />

    <string>選擇後不關閉選單(點兩下才關閉)</string>
    @Html.DropDownList("closeOnSelectFalse", (IEnumerable<SelectListItem>)ViewBag.AllCategories, null, new { @class = "form-control", @id = "closeOnSelectFalse" })
    <string style="color:red">選擇後不關閉選單(點兩下才關閉) 不能搭配Multiple使用!</string>
    <br /><br />

    <string>關閉後自動選擇已反白的選項</string>
    @Html.DropDownList("selectOnCloseTrue", (IEnumerable<SelectListItem>)ViewBag.AllCategories, null, new { @class = "form-control", @id = "selectOnCloseTrue", @multiple = "multiple" })
    <br /><br />


    <input type="submit" value="提交此頁面" />
}


@section Scripts
{
    <script type="text/javascript">
        $(document).ready(function () {
            //========選擇後自動關閉選單 Start========
            $("#closeOnSelectTrue").select2({
                placeholder: "選擇後自動關閉選單(預設)",
                closeOnSelect: true
            });

            //"選擇後不關閉選單(點兩下才關閉) 不能搭配Multiple使用!"
            $("#closeOnSelectFalse").select2({ closeOnSelect: false });
            //========選擇後自動關閉選單 End========

            //========關閉後自動選擇已反白的選項 Start========
            $("#selectOnCloseTrue").select2({
                placeholder: "關閉後自動選擇已反白的選項",
                selectOnClose: true,
            });
            //========關閉後自動選擇已反白的選項 End========

        })
    </script>
}

32行 預設為​true ,選了某項就直接關閉選單

36行 若改為false,選擇選項時需同一個選項兩次才會關閉(無法搭配multiple使用)

42行 點開下拉選單,若滑鼠移到某個選項,接著點選選單以外的地方關閉選單,此時就會自動選擇被反白的選項

點擊其他地方關閉選單時,就會自動選擇台灣文學​

 

    ================= 選擇後自動關閉;關閉時選擇反白選項 End =================

 

我沒有做出來,或沒有特別做的部分如下

/*補充
             1.清空選項
                   $('#mySelect2').val(null).trigger('change');

             2.取得被選取的選項
                 2-1 Using a jQuery selector $('#mySelect2').find(':selected');
                 2-2 Using the data method   $('#mySelect2').select2('data');
             
             3.destroy  The destroy method will remove the Select2 widget from the target element. It will revert back to a standard select control:
                   $('#mySelect2').select2('destroy');
                   //效果參考https://select2.org/programmatic-control/methods
             
             4.Listening for events
                    $('#mySelect2').on('select2:select', function (e) { Do something});

             
*/