Combining BootstrapTable and KnockoutJS to implement addition, deletion, modification, and query functions [2], bootstrapknockoutjs
In the previous article, I introduced the addition, deletion, modification, and query functions of BootstrapTable and KnockoutJS, and introduced some basic usage of knockout. js. Next, we will continue to introduce you through this article. If you plan to use ko for the project, check it out!
Bootstrap is a front-end framework that frees Web developers and shows a very high level of UI. Theoretically, you do not need to write a line of css. You only need to add the appropriate attributes to the tag.
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. effect Preview
In fact, there is no effect, that is, simple addition, deletion, modification, and query. The focus is on the Code. Using ko can greatly save interface DOM Data Binding operations. The following is the js Code for the entire addition, deletion, modification, and query logic:
Page effect:
Ii. Sample Code
Okay, let's go to the point! The blog focuses on two parts: The first part is the table initialization part, and the second part is the addition, deletion, and modification part of the button operation.
1. Table Initialization
1.1 preparations
First look at the js and css files to be referenced
<link href="~/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" /><link href="~/Content/bootstrap-table/bootstrap-table.min.css" rel="stylesheet" /><script src="~/scripts/jquery-1.9.1.min.js"></script><script src="~/Content/bootstrap/js/bootstrap.min.js"></script><script src="~/Content/bootstrap-table/bootstrap-table.min.js"></script><script src="~/Content/bootstrap-table/locale/bootstrap-table-zh-CN.js"></script><script src="~/scripts/knockout/knockout-3.4.0.min.js"></script><script src="~/scripts/knockout/extensions/knockout.mapping-latest.js"></script><script src="~/Content/bootstrap-table/knockout.bootstraptable.js"></script><script src="~/scripts/Department.js"></script>
These are common css and js files. Our custom js files mainly include knockout. bootstraptable. js and Department. js. In the previous article, we introduced how to use ko to customize our data-bind. Similarly, for table binding, we also define a custom binding in the Code knockout. bootstraptable. js.
// Add ko custom binding ko. bindingHandlers. myBootstrapTable = {init: function (element, valueAccessor, allBindingsAccessor, viewModel) {// here oParam is the bound viewmodelvar oViewModel = valueAccessor (); var $ ele = $ (element ). bootstrapTable (oViewModel. params); // Add the bootstrapTable method to the viewmodel. bootstrapTable = function () {return $ ele. bootstrapTable. apply ($ ele, arguments) ;}}, update: function (element, valueAccessor, allBindingsAccessor, viewModel) {}}; // initialize (function ($) {// Add the bootstrapTableViewModel method ko to ko. bootstrapTableViewModel = function (options) {var that = this; this. default = {search: true, // whether to display table search. this search is a client-side search and does not go to the server. Therefore, it is of little significance to me: strictSearch: true, showColumns: true, // whether to display cache: false, showRefresh: true, // whether to display the refresh button minimumCountColumns: 2, // clickToSelect: true, // enable or not click showToggle: true,}; this. params = $. extend ({}, this. default, options | {}); // obtain the selected record this. getSelections = function () {var arrRes = that. bootstrapTable ("getSelections") return arrRes ;}; // refresh this. refresh = function () {that. bootstrapTable ("refresh") ;};}) (jQuery );
Code: This js file mainly does two things:
1. Customize the data-bind attribute myBootstrapTable. You do not need to define the update method in ko. bindingHandlers. myBootstrapTable.
2. Add bootstrapTableViewModel to the ko object to encapsulate bootstrapTable.
1.2 html Tag start binding
<Table id = "tb_dept" data-bind = "myBootstrapTable: $ root "> <thead> <tr> <th data-checkbox =" true "> </th> <th data-field =" Name "> Department Name </th> <th data-field = "Level"> department Level </th> <th data-field = "Des"> description </th> <th data-field = "strCreatetime"> creation time </th> </tr> </thead> </table>
Code: defines a table label and binds it to myBootstrapTable. As mentioned in the previous article, $ root can be understood as initialization. For simplicity, all colums are directly written in <th>.
1.3 activate ko binding
After the page is loaded, start ko binding:
// Initialize $ (function () {// 1. initialize table tableInit. init (); // 2. register the add, delete, and modify event operate. operateInit () ;}); // initialize the table var tableInit = {Init: function () {// bind viewmodelthis to the table. myViewModel = new ko. bootstrapTableViewModel ({url: '/Department/GetDepartment', // request background URL (*) method: 'get', // Request method (*) toolbar: '# toolbar', // The container used by the tool button queryParams: function (param) {return {limit: param. limit, offset: param. offset };}, // pass the parameter (*) pagination: true, // whether to display the page (*) sidePagination: "server", // paging mode: client page, server Page (*) pageNumber: 1, // initialize the loading of the first page, default first page pageSize: 10, // The number of records per page (*) pageList: [10, 25, 50,100], // number of lines per page (*)}); ko. applyBindings (this. myViewModel, document. getElementById ("tb_dept "));}};
Code explanation: After the page is loaded, call the above encapsulated bootstrapTableViewModel object to merge and transfer the parameters, and then activate the binding and activate this. myViewModel as the bound viewmodel. The debugging code shows that when ko. applyBindings (this. myViewModel, document. getElementById ("tb_dept"); the custom binding takes effect only when the program enters ko. bindingHandlers. the init method of the myBootstrapTable object to initialize the bootstrapTable. Here, we need to note that:
Init: function (element, valueAccessor, allBindingsAccessor, viewModel) {// here oParam is the bound viewmodelvar oViewModel = valueAccessor (); var $ ele = $ (element ). bootstrapTable (oViewModel. params); // Add the bootstrapTable method to the viewmodel. bootstrapTable = function () {return $ ele. bootstrapTable. apply ($ ele, arguments );}}
In the init method above, through the second parameter valueAccessor, we get the currently bound viewmodel, that is, our above this. the blogger thinks this is helpful for you to understand the logic of custom binding. Basically, when var $ ele = $ (element). bootstrapTable (oViewModel. params) is executed, the table Initialization is complete. The method blogger corresponding to the background defines a set at will. For the sake of completeness, I will post it here:
DepartmentController
2. Button operations
Previously, we initialized the use of custom data-bind through bootstrapTable. The following button is used to experience the "refreshing" of monitoring attributes ".
2.1 view page
First, define the add, delete, modify button on the view page.
<Div id = "toolbar" class = "btn-group"> <button id = "btn_add" type = "button" class = "btn-default"> <span class = "glyphicon-plus" aria-hidden = "true"> </span> added </button> <button id = "btn_edit" type = "button" class = "btn -default "> <span class =" glyphicon-pencel "aria-hidden =" true "> </span> modify </button> <button id =" btn_delete "type = "button" class = "btn-default"> <span class = "glyphicon-remove" aria-hidden = "true"> </span> Delete </button> </div>
For ease of use, the blogger uses a hidden pop-up box to include new and edited text boxes. Of course, in general, some views may be used here, and there may be an Edit in your project. cshtml, but here the bloggers put these on a page, because this is not the focus of the text.
<Div class = "modal fade" id = "myModal" tabindex = "-1" role = "dialog" aria-labelledby = "myModalLabel"> <div class = "modal-dialog "role =" document "> <div class =" modal-content "> <div class =" modal-header "> <button type =" button "class =" close "data -dismiss = "modal" aria-label = "Close"> <span aria-hidden = "true"> × </span> </button>
2.2 JS initialization button operation
// Operate var operate = {// initialize the button event operateInit: function () {this. operateAdd (); this. operateUpdate (); this. operateDelete (); this. departmentModel = {id: ko. observable (), Name: ko. observable (), Level: ko. observable (), Des: ko. observable (), CreateTime: ko. observable () };}, // added operateAdd: function () {$ ('# btn_add '). on ("click", function () {$ ("# myModal "). modal (). on ("shown. bs. modal ", function () {var oEmptyModel = {id: k O. observable (), Name: ko. observable (), Level: ko. observable (), Des: ko. observable (), CreateTime: ko. observable ()}; ko. utils. extend (operate. departmentModel, oEmptyModel); ko. applyBindings (operate. departmentModel, document. getElementById ("myModal"); operate. operateSave ();}). on ('ddden. bs. modal', function () {ko. cleanNode (document. getElementById ("myModal") ;}) ;}, // edit operateUpdate: function () {$ ('# btn_e Dit '). on ("click", function () {$ ("# myModal "). modal (). on ("shown. bs. modal ", function () {var arrselectedData = tableInit. myViewModel. getSelections (); if (! Operate. operateCheck (arrselectedData) {return;} // converts the Model with data in the selected row to viewmodelko through the Mapping component. utils. extend (operate. departmentModel, ko. mapping. fromJS (arrselectedData [0]); ko. applyBindings (operate. departmentModel, document. getElementById ("myModal"); operate. operateSave ();}). on ('ddden. bs. modal', function () {// clear the binding when the pop-up box is closed (this clearing includes clearing the binding and clearing the registration event) ko. cleanNode (document. getElementById ("myModal") ;}) ;}, // Delete Except operateDelete: function () {$ ('# btn_delete '). on ("click", function () {var arrselectedData = tableInit. myViewModel. getSelections (); $. ajax ({url: "/Department/Delete", type: "post", contentType: 'application/json', data: json. stringify (arrselectedData), success: function (data, status) {alert (status); // tableInit. myViewModel. refresh () ;}}) ;}, // save operateSave: function () {$ ('# btn_submit '). on ("click ", Function () {// obtain the current viewmodelvar oViewModel = operate. DepartmentModel; // convert Viewmodel to data modelvar oDataModel = ko. toJS (oViewModel); var funcName = oDataModel. id? "Update": "Add"; $. ajax ({url: "/Department/" + funcName, type: "post", data: oDataModel, success: function (data, status) {alert (status); tableInit. myViewModel. refresh () ;}}) ;}, // operateCheck: function (arr) {if (arr. length <= 0) {alert ("Please select at least one row of Data"); return false;} if (arr. length> 1) {alert ("only one row of data can be edited"); return false;} return true ;}}
Code: Let's talk about the execution logic here. First, call operate. operateInit (); in the $ (function () {}) method ();. Register the Click Event of the button on the page in the operateInit () method, and define this. DepartmentModel as the newly added viewmodel. this viewmodel defines the monitoring attribute corresponding to the page element. Do you still remember some data-bind values in the hidden pop-up box above? Yes, the value corresponding to the value corresponds to the monitoring attribute here. After this setting is bound, all of the causes in js are as follows. changes monitored in the DepartmentModel will trigger changes in the value of these tags bound to the interface. On the contrary, changes in the Value of all tags on the interface, it is bound to cause changes in its monitoring property value, which is called bidirectional binding. Next, let's take a look at the execution of Bidirectional binding.
2.3 new operations
$('#btn_add').on("click", function () {$("#myModal").modal().on("shown.bs.modal", function () {var oEmptyModel = {id: ko.observable(),Name: ko.observable(),Level: ko.observable(),Des: ko.observable(),CreateTime: ko.observable()};ko.utils.extend(operate.DepartmentModel, oEmptyModel);ko.applyBindings(operate.DepartmentModel, document.getElementById("myModal"));operate.operateSave();}).on('hidden.bs.modal', function () {ko.cleanNode(document.getElementById("myModal"));});});
When the new operation is triggered on the interface, the hidden modal box mentioned above is displayed first. When the modal box is displayed, define an empty viewmodel and call ko. utils. extend (operate. departmentModel, oEmptyModel. departmentModel is overwritten by an empty viewmodel. Ko. utils. the function of extend () and $. similar to extend (), extend merges the previous Objects Based on the following objects. after merging, use the new viewmodel to activate the binding. After binding is activated, register the click Event of the Save button. In this case, the modal box is displayed. Because the monitoring attributes in the viewmodel are empty, the values of corresponding interface elements are also cleared. Therefore, we can see that:
When the pop-up box is closed, we execute ko. cleanNode (document. getElementById ("myModal"); this sentence is very important, because for the same dom, ko can only be bound once. If you need to bind it again, you need to clear the binding first, in addition, the cleanNode () method will not only empty the binding, but also the events registered in the dom will also be cleared. Pay attention to this when using it!
2.4 edit operations
$ ('# Btn_edit '). on ("click", function () {$ ("# myModal "). modal (). on ("shown. bs. modal ", function () {var arrselectedData = tableInit. myViewModel. getSelections (); if (! Operate. operateCheck (arrselectedData) {return;} // converts the Model with data in the selected row to viewmodelko through the Mapping component. utils. extend (operate. departmentModel, ko. mapping. fromJS (arrselectedData [0]); ko. applyBindings (operate. departmentModel, document. getElementById ("myModal"); operate. operateSave ();}). on ('ddden. bs. modal', function () {// clear the binding when the pop-up box is closed (this clearing includes clearing the binding and clearing the registration event) ko. cleanNode (document. getElementById ("myModal "));});});
When the edit operation is triggered, the page is displayed. In the pop-up event of the pop-up box, we get the selected row and verify whether a row is selected. It is best to pass ko. mapping. fromJS (arrselectedData [0]) converts a common Json object to a viewmodel with monitoring attributes. As mentioned above, this method requires knockout. mapping-latest.js support for this js file. After the conversion, update the viewmodel using the ko. utils. extend () method, and then activate the binding. The viewmodel is updated by the data of the currently selected row. The result is as follows:
2.5 save
After the "add" and "edit" dialog box appears, modify the relevant information and click "save". The "save" event is triggered.
$ ('# Btn_submit '). on ("click", function () {// obtain the current viewmodelvar oViewModel = operate. departmentModel; // convert Viewmodel to data modelvar oDataModel = ko. toJS (oViewModel); var funcName = oDataModel. id? "Update": "Add"; $. ajax ({url: "/Department/" + funcName, type: "post", data: oDataModel, success: function (data, status) {alert (status); tableInit. myViewModel. refresh ();}});});
When a save event is triggered, we first obtain the viewmodel bound to the page, that is, operate. departmentModel, and then use ko. the toJS () method converts a viewmodel with monitoring attributes to a Json object with pure data. This method is built-in to ko and does not require other js support. After obtaining the json object, send an ajax request to add or edit data. In this way, bidirectional binding is well reflected. After the value of all text boxes on the interface changes, operate. DepartmentModel changes.
2.6 delete operation
There is nothing to say about the delete operation, and it has little to do with ko.
Iii. Summary
The preceding simple addition, deletion, modification, and query operations introduce the combined use of ko and bootstrapTable. Ko can free you from DOM and focus on viewmodel. Looking at the js Code, jquery's val (), text (), and other operations on the Interface dom's value and value assignment are almost invisible. Are you looking clean and refreshing and tall ~~ Of course, this may only be some basic usage of ko. After all, it takes only three days for the blogger to learn ko. More advanced usage remains to be explored. After a while, I am familiar with it, I will share some of its advanced usage with you. If you think this article can help you understand ko's principles and some of its usage, I would like to recommend it. I am very grateful to you!
The above section describes how to use BootstrapTable and KnockoutJS to add, delete, modify, and query all the content. I hope it will be helpful to you!