KnockoutJS is a JavaScript-implemented MVVM framework. Next, we will introduce how Bootstrap and KnockoutJs work together to achieve paging effect. If you are interested in bootstrapknockoutjs, KnockoutJS is a JavaScript-implemented MVVM framework. Great. For example, after adding or removing list data items, you do not need to refresh the entire control segment or write JS add or delete nodes by yourself. You only need to pre-define the template and attributes that comply with its syntax definition. Simply put, we only need to pay attention to data access.
I. Introduction
I plan to use KnockoutJs to create a Web Front-end because the company's system needs to be revised recently. During the process, I encountered a problem-how to use KnockoutJs to complete the paging function. In the previous article, KnockoutJs is not used for paging. Therefore, in this article, KnockoutJs + Bootstrap is used for paging data display.
Ii. Implement paging using KnockoutJs
Two methods are used to implement paging. The first method is to load all the data and display all the data on pages. The second method is to load only part of the data each time, each request reloads the subsequent data.
For the two methods, pagination implemented using Razor usually uses the second method to implement paging. However, the first method also has advantages for single-page programs, the first implementation method can be used for not a very large amount of data, because, in this case, the subsequent data loading, the user experience is very smooth. So here we will introduce the two implementation methods respectively.
2.1 Implementation of loading part of data each time
The back-end code here uses the code from the previous article, but adds some sample data. The specific backend implementation code is:
////// Web API service, providing data services for the Web Front-end ///Public class TaskController: ApiController {private readonly TaskRepository _ taskRepository = TaskRepository. Current; public IEnumerable
GetAll () {return _ taskRepository. getAll (). orderBy (a =>. id);} [Route ("api/task/GetByPaged")] public PagedModel GetAll ([FromUri] int pageIndex) {const int pageSize = 3; int totalCount; var tasks = _ taskRepository. getAll (pageIndex, pageSize, out totalCount ). orderBy (a =>. id); var pageData = new PagedModel () {PageIndex = pageIndex, PagedData = tasks. toList (), TotalCount = totalCount, PageCount = (totalCount + pageSize-1)/pageSize}; // return data return pageData ;}}///
/// Task warehousing encapsulates all database operations ///Public class TaskRepository {# region Static Filed private static Lazy
_ TaskRepository = new Lazy
() => New TaskRepository (); public static TaskRepository Current {get {return _ taskRepository. Value ;}# endregion # region Fields private readonly List
_ Tasks = new List
() {New Task {Id = 1, Name = "Create a SPA program", Description = "SPA (single page web application), the advantage of SPA is a small amount of bandwidth, smooth Experience ", Owner =" Learning hard ", FinishTime = DateTime. parse (DateTime. now. addDays (1 ). toString (CultureInfo. invariantCulture)}, new Task {Id = 2, Name = "Learning KnockoutJs", Description = "KnockoutJs is an MVVM class library that supports two-way binding", Owner = "Tommy Li ", finishTime = DateTime. parse (DateTime. now. addDays (2 ). toString (Cult UreInfo. InvariantCulture)}, new Task {Id = 3, Name = "Learning AngularJS", Description = "AngularJs is an MVVM framework that integrates MVVM and MVC. ", Owner =" Li Zhi ", FinishTime = DateTime. parse (DateTime. now. addDays (3 ). toString (CultureInfo. invariantCulture)}, new Task {Id = 4, Name = "Learning ASP. net mvc Website ", Description =" Glimpse is. the performance testing tool under. NET supports asp.net, asp.net mvc, EF, and so on. The advantage is that it does not need to modify any code of the original project and can output the execution time of each stage of code execution ", owner = "Tonny Li", FinishTime = DateTime. parse (DateTime. now. addDays (4 ). toString (CultureInfo. invariantCulture)}, new Task {Id = 5, Name = "test Task 1", Description = "test Task 1", Owner = "Li Zhi", FinishTime = DateTime. parse (DateTime. now. addDays (5 ). toString (CultureInfo. invariantCulture)}, new Task {Id = 6, Name = "test Task 2", Description = "test Task 2", Owner = "Li Zhi", FinishTime = DateTime. parse (DateTime. now. addDays (6 ). toString (CultureInfo. invariantCulture)}, new Task {Id = 7, Name = "test Task 3", Description = "test Task 3", Owner = "Li Zhi", FinishTime = DateTime. parse (DateTime. now. addDays (7 ). toString (CultureInfo. invariantCulture) },}; # endregion # region Public Methods public IEnumerable
GetAll () {return _ tasks;} public IEnumerable
GetAll (int pageNumber, int pageSize, out int totalCount) {var skip = (pageNumber-1) * pageSize; var take = pageSize; totalCount = _ tasks. count; return _ tasks. skip (skip ). take (take);} public Task Get (int id) {return _ tasks. find (p => p. id = id);} public Task Add (Task item) {if (item = null) {throw new ArgumentNullException ("item");} item. id = _ tasks. count + 1; _ tasks. add (item); return item;} public void Remove (int id) {_ tasks. removeAll (p => p. id = id);} public bool Update (Task item) {if (item = null) {throw new ArgumentNullException ("item");} var taskItem = Get (item. id); if (taskItem = null) {return false;} _ tasks. remove (taskItem); _ tasks. add (item); return true ;}# endregion}
Web Front-end implementation code:
@ {ViewBag. Title = "Index2"; Layout = "~ /Views/Shared/_ Layout. cshtml ";}Paging method 2-task list
No. |
Name |
Description |
Owner |
Creation Time |
Completion Time |
Status |
|
|
|
|
|
|
|
|
There are a total of records, each page displays:
|
The corresponding Js implementation is:
// The second method for implementing paging var ListViewModel2 = function () {// viewModel itself. Used to prevent confusion in scope var self = this; self when this is used directly. loadingState = ko. observable (true); self. pageSize = ko. observable (3); // data this. pagedList = ko. observableArray (); // the page number to be accessed this. pageIndex = ko. observable (1); // the total number of pages this. pageCount = ko. observable (1); // number of page numbers this. allPages = ko. observableArray (); // current page this. currengePage = ko. observable (1); self. totalCount = ko. observable (1); this. refresh = function () {// limit the requested page number within the range of this data page if (se Lf. pageIndex () <1) self. pageIndex (1); if (self. pageIndex ()> self. pageCount () {self. pageIndex (self. pageCount ();} // post asynchronously loads the data sendAjaxRequest ("GET", function (data) {// remove the original data self before loading the new data. pagedList. removeAll (); self. allPages. removeAll (); self. totalCount (data. totalCount); self. pageCount (data. pageCount); self. loadingState (false); for (var I = 1; I <= data. pageCount; I ++) {// load page number self. allPages. push ({page Number: I});} // for... in statements are used to perform cyclic operations on the attributes of arrays or objects. // For... the code in the in loop performs an operation on the element or object attribute of the array every time it is executed. For (var I in data. pagedData) {// load data self. pagedList. push (data. pagedData [I]) ;}}, 'getbypaged', {'pageindex': self. pageIndex ()}) ;}; // request the first page of data this. first = function () {self. pageIndex (1); self. refresh () ;}; // request the next page of data this. next = function () {self. pageIndex (this. pageIndex () + 1); self. refresh () ;}; // request the previous page of data this. previous = function () {self. pageIndex (this. pageIndex ()-1); self. refresh () ;}; // request the last page of data this. last = Function () {self. pageIndex (this. pageCount ()-1); self. refresh () ;}; // jump to a page this. gotoPage = function (data, event) {self. pageIndex (data); self. refresh () ;};}; function sendAjaxRequest (httpMethod, callback, url, reqData) {$. ajax ("/api/task" + (url? "/" + Url: ""), {type: httpMethod, success: callback, data: reqData}) ;}$ (document ). ready (function () {var viewModel = new ListViewModel2 (); viewModel. refresh (); if ($ ('# list2 '). length) ko. applyBindings (viewModel, $ ('# list2 '). get (0 ));});
The following describes how to implement the paging function using KnockoutJs:
1. After the page is loaded, initiate an Ajax request to asynchronously call the REST service to request some data.
2. Then bind the requested data to display through KnockoutJs.
3. Bind the corresponding page information to the Bootstrap page
4. When you click to flip the page, initiate an Ajax request to asynchronously call the Rest service request data and then display the request data.
The above describes the call logic of the code. You can refer to the corresponding JS Code to understand the above description. The second implementation method is complete.
2.2 load all data for the first time and display all data on pages
Next we will introduce the first implementation method. In this way, the user will only feel the data loading during the first time, but cannot feel the page loading during the page turning process, in this way, the user experience is smoother when there are not too many data.
The specific implementation method is to display not all request data on the page. Because there is too much data, the user may be dazzled when it is displayed on the page. Display the data on multiple pages to make the user's viewing clearer.
The specific implementation code of Web Front-end Js is:
Var ListViewModel = function () {var self = this; window. viewModel = self; self. list = ko. observableArray (); self. pageSize = ko. observable (3); self. pageIndex = ko. observable (0); // page number to access self. totalCount = ko. observable (1); // The total number of records self. loadingState = ko. observable (true); self. pagedList = ko. dependentObservable (function () {var size = self. pageSize (); var start = self. pageIndex () * size; return self. list. slice (start, start + size) ;}); self. maxPageIndex = ko. dependentObservable (function () {return Math. ceil (self. list (). length/self. pageSize ()-1 ;}); self. previousPage = function () {if (self. pageIndex ()> 0) {self. pageIndex (self. pageIndex ()-1) ;}}; self. nextPage = function () {if (self. pageIndex () <self. maxPageIndex () {self. pageIndex (self. pageIndex () + 1) ;}}; self. allPages = ko. dependentObservable (function () {var pages = []; for (var I = 0; I <= self. maxPageIndex (); I ++) {pages. push ({pageNumber: (I + 1)}) ;}return pages ;}); self. moveToPage = function (index) {self. pageIndex (index) ;};}; var listViewModel = new ListViewModel (); function bindViewModel () {sendAjaxRequest ("GET", function (data) {listViewModel. loadingState (false); listViewModel. list (data); listViewModel. totalCount (data. length); if ($ ('# list '). length) ko. applyBindings (listViewModel, $ ('# list '). get (0) ;}, null, null) ;}$ (document ). ready (function () {bindViewModel ();});
Its front-end page implementation is similar to the previous implementation. The page code is as follows:
@ {ViewBag. Title = "Index"; Layout = "~ /Views/Shared/_ Layout. cshtml ";}Task List
No. |
Name |
Description |
Owner |
Creation Time |
Completion Time |
Status |
|
|
|
|
|
|
|
|
There are a total of records, each page displays:
|
Iii. Running Effect
Next, let's take a look at the paging effect implemented by KnockoutJs:
Iv. Summary
Here, the content to be introduced in this article is over. Although the content implemented in this article is relatively simple, for some friends who are new to KnockoutJs, I believe that the implementation of this article will be a lot of guidance. Next, I will share with you about AngularJs.
The above is a detailed description of how Bootstrap and KnockoutJs are combined to implement paging effect instances. I hope to help you!