Trong ví dụ này mình sẽ chia sẻ với các bạn về cách xây dựng tính năng Autocomplete Texbox trên Asp.Net MVC5 với jQuery Typeahead . Với sự hỗ trợ của JqueryTypeHead chúng ta có thể xây dựng được một tính năng gọi ý tìm kiếm nâng cao, cho phép với mỗi từ khóa người dùng gõ trên ô tìm kiếm, sẽ đưa ra được một danh sách gợi ý phân loại một cách rất trực quan và rõ ràng.
Các bạn xem hình trên, ví dụ khi người dùng gõ từ khóa "samsung" thì gợi ý tìm kiếm sẽ phân biệt ra là đang muốn tìm theo tên điện thoại "phone" hay tìm theo hãng điện thoại "brand". Từ đó người dùng sẽ có được một cái nhìn trực quan hơn trong tìm kiếm, và chức năng gọi ý tìm kiếm autocomplete sẽ mang lại hiệu quả cao hơn trong trường hợp này.
1. Download jQuery Typeahead
Các bạn có thể tìm hiểu về thư viện này và download về tại link sau:
http://www.runningcoder.org/jquerytypeahead/
http://www.runningcoder.org/jquerytypeahead/
2. Tích hợp jQuery Typeahead vào project
Trong page _Layout.cshtml ta chỉ cần kéo css vào phần <head>
1
| <link href="~/Content/jquery.typeahead.min.css" rel="stylesheet" /> |
Và file javascript vào phía cuối trang
1
| <script src="~/Scripts/jquery.typeahead.min.js"></script> |
3. Tạo Database
Đâu tiên chúng ta tạo 1 database với dữ liệu test, sau đó sẽ viết hàm API lấy dữ liệu suggest từ database này.
Trong source code ví dụ đính kèm cuối bài viết, các bạn chạy file ~/ScriptDatabase/ScriptDatabase.sql để tạo Database
4. Viết hàm API lấy dữ liệu suggest
Chúng ta có thể cung cấp dữ liệu gợi ý cho jQuery Typeahead dưới dạng json data (xem thêm tại đây), do vậy với Database test vừa tạo ở trên, chúng ta cần viết 1 hàm trả về json data cho jQuery Typeahead
HomeController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| //init data for autocomplete filter public JsonResult GetValueAutoComplate() { AutoCompleteView returnObj = new AutoCompleteView(); using (var db = new AutoComplateDatabaseEntities()) { returnObj.Phones = new List<ItemView>(); var queryPhone = from p in db.Phones join b in db.Brands on p.BrandId equals b.Id select new ItemView() { Id = p.Id, Name = p.Name, Description = p.Description + " " + b.Name }; returnObj.Phones = queryPhone.ToList(); returnObj.Brands = new List<ItemView>(); var queryBrand = from b in db.Brands select new ItemView() { Id = b.Id, Name = b.Name, Description = b.Description }; returnObj.Brands = queryBrand.ToList(); } return Json(returnObj, JsonRequestBehavior.AllowGet); } |
Tạo class ~/Models/AutoCompleteView.cs cho hàm trên.
AutoCompleteView.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| using System.Collections.Generic; namespace AutoCompleteSearch.Models { public class AutoCompleteView { public List<ItemView> Phones { set ; get ; } //iphone 4, iphone 5, samsung galaxy s8... public List<ItemView> Brands { set ; get ; } //apple, samsung, xixaomin } public class ItemView { public int Id { set ; get ; } public string Name { set ; get ; } public string Description { set ; get ; } public string Icon { set ; get ; } } } |
5. Tích hợp jQuery Typeahead vào page
Và cuối cùng ta cần đưa form search của jQuery Typeahead vào trên trang (nơi bạn muốn đặt form tìm kiếm), ví dụ này mình sẽ để form search ở page index.cshtml
Index.cshtml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| @model AutoCompleteSearch.Models.IndexView @{ ViewBag.Title = "Home Page"; } <h2>Auto complete search with jquery-typehead</h2> <hr /> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="row"> <div class="col-md-3"> @*Input auto complete*@ <div class="typeahead__container"> <div class="typeahead__field"> <span class="typeahead__query"> <input class="js-typeahead" name="q" type="search" placeholder="Enter product name or brand" autocomplete="off"> </span> </div> </div> @*hidden value for search*@ @Html.HiddenFor(x=>x.Keyword, new { @id= "Keyword" }) @Html.HiddenFor(x => x.Type, new { @id = "TypeSearch" }) </div> <div class="col-md-4"> @*Submit button*@ <input type="submit" name="submit" value="Search" class="btn btn-primary" /> </div> </div> } |
Chúng ta cần tạo thêm class ~/Models/IndexView.cs để lưu trạng thái tìm kiếm lựa chọn và từ khóa tìm kiếm
IndexView.cs
1
2
3
4
5
6
7
8
| namespace AutoCompleteSearch.Models { public class IndexView { public string Type { set ; get ; } public string Keyword { set ; get ; } } } |
Tiếp theo ta cần thêm hàm javascript của jQuery Typehead để thực hiện việc lấy dữ liệu tìm kiếm và hiện thị gợi ý ngay dưới textbox search
Index.cshtml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| @section scripts{ <script> $.typeahead({ input: ".js-typeahead" , order: "asc" , hint: true , group: { template: "{{group}}" }, maxItemPerGroup: 5, template: function (query, item) { return "<div class='suggest-item'>{{Name}} - <small>{{Description}}</small></div>" ; }, source: { "Phones" : { ajax: { url: "/Home/GetValueAutoComplate" , path: "Phones" }, display: "Name" }, "Brands" : { ajax: { url: "/Home/GetValueAutoComplate" , path: "Brands" }, display: "Name" } }, callback: { onClickAfter: function (node, a, item, event) { $( '#TypeSearch' ).val(item.group); $( '#Keyword' ).val(item.Name); } } }); </script> } |
Ở hàm trên, trong sự kiện onClickAfter ta cần lưu lại từ khóa #Keyword và kiểu tìm kiếm #TypeSearch (Tìm theo tên sản phẩm, hay tìm theo loại sản phẩm) lại để xử lý cho việc redirect đến trang tìm kiếm phù hợp.
Ví dụ khi người dùng thực hiện tìm kiếm với gợi ý autocomplete hiện ra, sẽ xẩy ra 3 trường hợp sau:
- Người dùng click vào tên sản phẩm trên ô gợi ý -> Redirect sang trang SearchPhone.cshtml (nếu sản phẩm là duy nhất thì có thể xử lý redirect đến page ProductDetail.cshtml)
- Người dùng click vào tên loại sản phẩm trên ô gợi ý -> Redirect sang trang SearchBrand.cshtml
- Người dùng không click vào gợi ý tìm kiếm mà gõ từ khóa rồi click search -> Redirect sang trang SearchAll.cshtml
Với 3 trường hợp có thể xẩy ra ở trên, ta sẽ viết hàm xử lý redirect ở HomeController như sau (xử lý tìm kiếm khi người dùng click button Search)
HomeController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| [HttpPost, ValidateAntiForgeryToken] public ActionResult Index(IndexView obj) { if (obj.Type == "Phones" ) return RedirectToAction( "SearchPhone" , "Home" , new { keyword = obj.Keyword }); else if (obj.Type == "Brands" ) return RedirectToAction( "SearchBrand" , "Home" , new { keyword = obj.Keyword }); else return RedirectToAction( "SearchAll" , "Home" , new { keyword = obj.Keyword }); } public ActionResult SearchAll( string keyword) { return View(); } public ActionResult SearchPhone( string keyword) { return View(); } public ActionResult SearchBrand( string keyword) { return View(); } |
Lúc đó, với dữ liệu tìm kiếm trả về tương ứng với mỗi trường hợp tìm kiếm, các bạn có thể xử lý tìm kiếm và hiện thị kết quả cho phù hợp.
6. Xử lý gợi ý tìm kiếm với tiếng việt không dấu.
Với chức năng hiện tại, giả sử trong CSDL gợi ý của chúng ta có từ khóa "Đà Nẵng" nhưng người dùng gõ "da nang" thì sẽ không hiện thị được gợi ý.
Để giải quyết vấn đề này jQuery Typeahead có hỗ trợ option accent, ta cần thêm đoạn code javascript này vào đoạn mã javascript ở ngoài page Index.cshtml ở phía trên.
1
2
3
4
5
6
7
8
9
10
11
12
| <script> $.typeahead({ input: ".js-typeahead" , ........ accent:{ from: "aáàãảạâấầẫẩậăắằẵẳặeéèẽẻẹêếềễểệiíìĩỉịoóòõỏọôốồỗổộơớờỡởợuúùũủụưứừữửựyýỳỹỷỵđ" , to: "aaaaaaaaaaaaaaaaaaeeeeeeeeeeeeiiiiiioooooooooooooooooouuuuuuuuuuuuyyyyyyd" }, ....... }); </script> |
Nguồn: http://thuyvk.com
0 comments: