Use the BootstrapTable component method in the ABP framework, abpbootstraptable

Source: Internet
Author: User

Use the BootstrapTable component method in the ABP framework, abpbootstraptable

1. About the ABP

"ASP. NET Boilerplate Project (ASP. NET sample project) "short for, it is a mature open-source framework, based on the DDD + Repository mode, comes with Zero permissions and Authentication Modules, avoiding the trouble of building a framework from scratch. The advantages of the ABP framework are stuck here, because it will be three days and three nights away from the text topic.

The blogger doesn't want to talk too much about the ABC entry. There are many entry-level articles about tkb in the garden to Jian and Sun mingrui. If you are interested, you can find out whether to provide its official website and source address.

ABC Official Website: http://www.aspnetboilerplate.com

Open Source Project: https://github.com/aspnetboilerplate

PS: If you don't want to see its source code, you can directly view the ABC official website on the demo address: https://aspnetzero.com /? Ref = abptmplpage

Click create my demo. The DEMO address is automatically generated for you.

Enter the corresponding Demo URL

Log in with the demo username and password

We can see the Implementation Effect of the Zero module.

II. Application of jTable in ABP

If you download the source code and select the hybrid development mode (the ABP provides two development modes, one is Angular Based on MVVM. js mode; the other is the mixed development mode of MVC + jQuery), such:

After you go Down the source code, you will find that all the UI tables in the source code of the ABP are implemented using jTable. Why is jTable used? The reason is simple. jTable is an open-source plug-in written by kalkan, the author of ABP. You must write your own stuff. The following jTable results are displayed.

To a jtable parent and child table:

If it is a simple table without a parent-child table, the effect of jTable is actually okay, but with some complex features, the blue area of the piece cannot bear to look straight, in addition, jTable APIs need to be improved, and many required functions need to be implemented by themselves. Therefore, we have received the need to replace all the table components with BootstrapTable, so that we can have today's topic: encapsulate BootstrapTable In the ABP.

Iii. Bootstrap Table Encapsulation

Upon receiving the requirement, the blogger's various Baidu and Google cannot find the Bootstrap Table component's encapsulation in the ABP, and some simply initialize the component in the traditional way in the project of the ABP, this is not what bloggers want. Speaking of this, you have to mention that if you encounter some problems in the process of using the ABC Development, you will find it difficult to search for relevant answers from Baidu, which can be found in Google sometimes, however, most of them are in the English community, so if you are weak in English, you will suffer a lot in searching for information. Sometimes a simple configuration problem may take a long time.

1. jTable initialization in the ABP Project

First, let's take a look at how jTable is initialized in a general ABP project. For example, we have the following interface and implementation in the Application:

 public interface IRequisitionAppService : IApplicationService {  Task<PagedResultDto<RequisitionListDto>> GetRequisitionListAsync(GetRequisitionListInput input); }  [AbpAuthorize(OrderAppPermissions.Pages_Order_Requisition)] public class RequisitionAppService : AbpZeroTemplateAppServiceBase, IRequisitionAppService {  private readonly IRepository<Requisition, long> _requisitionRepository;  public RequisitionAppService(IRepository<Requisition, long> requisitionRepository)  {   _requisitionRepository = requisitionRepository;  }     public async Task<PagedResultDto<RequisitionListDto>> GetRequisitionListAsync(GetRequisitionListInput input)  {   var query = _requisitionRepository.GetAll()             .WhereIf(input.Status != null, w => (int)w.Status == input.Status.Value)             .WhereIf(              !input.Filter.IsNullOrWhiteSpace(),              u =>               u.No.Contains(input.Filter) ||               u.Remark.Contains(input.Filter)             );   var count = await query.CountAsync();   var list = await query   .OrderBy(input.Sorting)   .PageBy(input)   .ToListAsync();   var dtos = list.MapTo<List<RequisitionListDto>>();   return new PagedResultDto<RequisitionListDto>(    count,    dtos    );  } }

Then we have a list of data on the front-end page obtained from this interface GetRequisitionListAsync ().

<Div class = "portlet-body"> <div id = "dataListTable"> </div> (function () {$ (function () {var _ $ dataListTable =$ ('# dataListTable'); var _ service = abp. services. app. requisition; _ $ dataListTable. jtable ({paging: true, sorting: true, selecting: true, actions: {listAction: {method: _ service. getRequisitionListAsync }}, fields: {id: {key: true, list: false}, details: {width: '1% ', sorting: false, edit: false, create: false, listClass: 'child-opener-image-column ', display: function (detailData) {var $ img = $ (' '); $ img. click (function () {_ $ dataListTable. jtable ('openchildtable', $ img. closest ('tr'), {title: "subscription details", showCloseButton: true, actions: {listAction: {method: _ service. getRequisitionDetailListByIdAsync }}, fields: {materialClassParentNameAndName: {title: app. localize ('materialclassname'), width: '8% '}, materialInfoTypeNo: {title: app. localize ('typeno'), width: '5% '}, materialInfoLengthDisplayName: {title: app. localize ('lengthdisplayname'), width: '3% '}, materialInfoWeight: {title: app. localize ('weight'), width: '5% ', display: function (data) {return data. record. materialInfoMinWeight + '-' + data. record. materialInfoMaxWeight; }}, materialInfoMouldTypeDisplayName: {title: app. localize ('mouldtypedisplayname'), width: '6% '}, materialInfoProductionRemark: {title: app. localize ('produmark remark'), width: '8% '}, materialInfoBundleCountDisplayName: {title: app. localize ('bundlecountdisplayname'), width: '3% '}, materialInfoUnitDisplayName: {title: app. localize ('unitdisplayname'), width: '3% '}, materialInfoProcessCost: {title: app. localize ('processcost'), width: '6% '}, materialInfoProductRemark: {title: app. localize ('productremark'), width: '6% '}, materialInfoRemark: {title: app. localize ('remark'), width: '6% '}, count: {title: app. localize ('purchase qty '), width: '6%'}, remark: {title: app. localize ('purchase note'), width: '6% '}}, function (data) {data. childTable. jtable ('load', {requisitionId: detailData. record. id}) ;}); return $ img ;}, no: {title: "purchase order no.", width: '000000'}, creatorUserName: {title: "Purchaser", width: '000000'}, creationTime: {title: "subscription time", width: '000000', display: function (data) {return moment (data. record. creationTime ). format ('yyyy-MM-DD HH: mm: ss') ;}}, sumCount: {title: "Total", width: '000000'}, status: {title: "status", width: '000000', display: function (data) {if (data. record. status = app. order. requisitionAuditStatus. audit) return '<span class = "label-info">' + app. localize ('autdit ') +' </span> 'else if (data. record. status = app. order. requisitionAuditStatus. auditPass) return '<span class = "label-success">' + app. localize ('pass') + '</span> 'else if (data. record. status = app. order. requisitionAuditStatus. auditReject) return '<span class = "label-danger">' + app. localize ('reobject') + '</span> 'else if (data. record. status = app. order. requisitionAuditStatus. delete) return '<span class = "label-danger">' + app. localize ('abandon') + '</span> 'else return' <span class = "label-danger"> '+ app. localize ('unknown ') +' </span> '}}}});});})();

The following results are obtained:

Code:

(1)var _service = abp.services.app.requisitionThis statement specifies the service to be used on the current page.

(2)_service.getRequisitionListAsyncThis sentence corresponds to the method called by the service. You will find that the method name in the background is GetRequisitionListAsync (), but it becomesgetRequisitionListAsync()For the moment, we call it a "hidden rule ".

2. bootstrapTable encapsulation in the ABP Project

Through the above Code, you will find that the methods defined in the application layer by the ABP will eventually generate some js functions, which is difficult here. We searched the api of the bootstrapTable component and did not get data through a function. How can this be done? For this problem, the blogger struggled for two days. At first, the blogger thought that the function would not be replaced by an http request. We only need to get the url of the http request and then convert the function to a url:

We declare {url: '/api/services/app/requisition/GetRequisitionListAsync'} When initializing using the bootstrapTable component. Isn't that enough? Well, after testing, the data can be obtained correctly. But it is not ideal, because the prefix above is generated by the ABC for us, whether it will change or not. It is really uncomfortable to add such a long string to every url, So I further thought, can we use function to initialize our bootstrapTable? If there is no component, can we not extend it to him? We don't need a url to get the data. We can call this function to get the data and then render the data to the component. There are two challenges: first, how can we change the original url Method to the function call method here? Second, encapsulation of parameters. After checking the source code of the component, it is found that if the component is on the server page, the component eventually enters the initServer () method to obtain data, and then renders it to the original initServer () of the component on the page () the method is as follows:

BootstrapTable.prototype.initServer = function (silent, query) {  var that = this,   data = {},   params = {    pageSize: this.options.pageSize === this.options.formatAllRows() ?     this.options.totalRows : this.options.pageSize,    pageNumber: this.options.pageNumber,    searchText: this.searchText,    sortName: this.options.sortName,    sortOrder: this.options.sortOrder   },   request;  if (!this.options.url && !this.options.ajax) {   return;  }  if (this.options.queryParamsType === 'limit') {   params = {    search: params.searchText,    sort: params.sortName,    order: params.sortOrder   };   if (this.options.pagination) {    params.limit = this.options.pageSize === this.options.formatAllRows() ?     this.options.totalRows : this.options.pageSize;    params.offset = this.options.pageSize === this.options.formatAllRows() ?: this.options.pageSize * (this.options.pageNumber - 1);   }  }  if (!($.isEmptyObject(this.filterColumnsPartial))) {   params['filter'] = JSON.stringify(this.filterColumnsPartial, null);  }  data = calculateObjectValue(this.options, this.options.queryParams, [params], data);  $.extend(data, query || {});  // false to stop request  if (data === false) {   return;  }  if (!silent) {   this.$tableLoading.show();  }  request = $.extend({}, calculateObjectValue(null, this.options.ajaxOptions), {   type: this.options.method,   url: this.options.url,   data: this.options.contentType === 'application/json' && this.options.method === 'post' ?    JSON.stringify(data) : data,   cache: this.options.cache,   contentType: this.options.contentType,   dataType: this.options.dataType,   success: function (res) {    res = calculateObjectValue(that.options, that.options.responseHandler, [res], res);    that.load(res);    that.trigger('load-success', res);   },   error: function (res) {    that.trigger('load-error', res.status, res);   },   complete: function () {    if (!silent) {     that.$tableLoading.hide();    }   }  });  if (this.options.ajax) {   calculateObjectValue(this, this.options.ajax, [request], null);  } else {   $.ajax(request);  } };

It is easy to understand the code, parse parameters, integrate parameters, GET parameters, send ajax requests, and render the data in the success event to the interface. After reading this code, it is much easier to encapsulate the function.

The encapsulated code is as follows:

(Function ($) {'use strict '; // debugger; // obtain the initialization method in bootstrapTable through the constructor var BootstrapTable = $. fn. bootstrapTable. constructor, _ initData = BootstrapTable. prototype. initData, _ initPagination = BootstrapTable. prototype. initPagination, _ initBody = BootstrapTable. prototype. initBody, _ initServer = BootstrapTable. prototype. initServer, _ initContainer = BootstrapTable. prototype. initContainer; // rewrite Boots TrapTable. prototype. initData = function () {_ initData. apply (this, Array. prototype. slice. apply (arguments) ;}; BootstrapTable. prototype. initPagination = function () {_ initPagination. apply (this, Array. prototype. slice. apply (arguments) ;}; BootstrapTable. prototype. initBody = function (fixedScroll) {_ initBody. apply (this, Array. prototype. slice. apply (arguments) ;}; BootstrapTable. prototype. initServe R = function (silent, query) {// construct a custom parameter for (var key in this. options. methodParams) {$. fn. bootstrapTable. defaults. methodParams [key] = this. options. methodParams [key];} // if the url is passed, the original logic if (this. options. url) {_ initServer. apply (this, Array. prototype. slice. apply (arguments); return;} // if the abpMethod is defined, the logic of the abpMethod if (! This. options. abpMethod) {return;} var that = this, data = {}, params = {pageSize: this. options. pageSize = this. options. formatAllRows ()? This. options. totalRows: this. options. pageSize, pageNumber: this. options. pageNumber, searchText: this. searchText, sortName: this. options. sortName, sortOrder: this. options. sortOrder}, request; // debugger; if (this. options. queryParamsType === 'limit') {params = {search: params. searchText, sort: params. sortName, order: params. sortOrder}; if (this. options. pagination) {params. limit = this. options. PageSize = this. options. formatAllRows ()? This. options. totalRows: this. options. pageSize; params. offset = this. options. pageSize = this. options. formatAllRows ()? 0: this. options. pageSize * (this. options. pageNumber-1) ;}} if (! ($. IsEmptyObject (this. filterColumnsPartial) {params ['filter'] = JSON. stringify (this. filterColumnsPartial, null);} data = $. fn. bootstrapTable. utils. calculateObjectValue (this. options, this. options. queryParams, [params], data); $. extend (data, query | {}); // false to stop request if (data = false) {return;} if (! Silent) {this. $ tableLoading. show ();} this. options. abpMethod (data ). done (function (result) {result = $. fn. bootstrapTable. utils. calculateObjectValue (that. options, that. options. responseHandler, [result], result); that. load (result); that. trigger ('Load-success ', result) ;}); request =$. extend ({}, $. fn. bootstrapTable. utils. calculateObjectValue (null, this. options. ajaxOptions), {type: this. options. meth Od, url: this. options. url, data: this. options. contentType = 'application/json' & this. options. method = 'post '? JSON. stringify (data): data, cache: this. options. cache, contentType: this. options. contentType, dataType: this. options. dataType, success: function (res) {debugger; res = $. fn. bootstrapTable. utils. calculateObjectValue (that. options, that. options. responseHandler, [res], res); that. load (res); that. trigger ('Load-success ', res);}, error: function (res) {that. trigger ('Load-error', res. status, res );}, Complete: function () {if (! Silent) {that. $ tableLoading. hide () ;}}); if (this. options. ajax) {$. fn. bootstrapTable. utils. calculateObjectValue (this, this. options. ajax, [request], null);} else {$. ajax (request) ;}} BootstrapTable. prototype. initContainer = function () {_ initContainer. apply (this, Array. prototype. slice. apply (arguments);}; abp. bootstrapTableDefaults = {striped: false, classes: 'table table-striped table-bordered table-advance table-hover ', pagination: true, cache: false, sidePagination: 'server ', uniqueId: 'id', showRefresh: false, search: false, method: 'post', // toolbar: '# toolbar', pageSize: 10, paginationPreText: 'prepage ', paginationNextText: 'Next page', queryParams: function (param) {// $. fn. bootstrapTable. defaults. methodParams. propertyIsEnumerable () var abpParam = {Sorting: param. sort, filter: param. search, skipCount: param. offset, maxResultCount: param. limit}; for (var key in $. fn. bootstrapTable. defaults. methodParams) {abpParam [key] = $. fn. bootstrapTable. defaults. methodParams [key];} return abpParam;}, responseHandler: function (res) {if (res. totalCount) return {total: res. totalCount, rows: res. items}; else return {total: res. result. totalCount, rows: res. result. items };}, methodParams :{}, abpMethod: function () {}}; $. extend ($. fn. bootstrapTable. ults, abp. bootstrapTableDefaults);}) (jQuery );

Code explanation: Two Parameters methodParams :{}, abpMethod: function () {} are added to obtain the functions and parameters of the abp. If the abpMethod is defined when the data is obtained, use the function to obtain data. Otherwise, the original logic is used.

Then the call is simple.

// Select the table var _ $ SendOrdersTable =$ ('# SendOrdersTable') on the page for data first. // obtain the var _ SendOrderService = abp method of the service layer. services. app. sendOrder; _ $ SendOrdersTable. bootstrapTable ({abpMethod: _ SendOrderService. getSendOrderListAsync, detailView: true, onExpandRow: function (index, row, $ detail) {var cur_table = paidetail.html ('<table> </table> '). find ('table'); $ (cur_table ). bootstrapTable ({showRefresh: false, search: false, pagination: false, abpMethod: _ SendOrderService. getSendOrderDetailListAsync, methodParams: {SendOrderId: row. id}, columns: [{field: 'materialclassname', title: app. localize ('materialclassname'), width: '8% '}, {field: 'typeno', title: app. localize ('typeno'), width: '8% '}]}) ;}, columns: [{field: 'no', title: app. localize ('sendorderno'), align: 'center'}, {field: 'suppliername', title: app. localize ('suppliername'), align: 'center'}, {title: app. localize ('sendordertime'), align: 'center', field: 'createddate', formatter: function (data) {return moment (data ). format ('yyyy-MM-DD HH: mm: ss') ;},{ field: 'status', align: 'center', title: app. localize ('sendorderstatus'), formatter: function (data) {var value = ""; if (data = 1) {value = '<span class = "label-info">' + app. localize ('autdit ') +' </span> ';} else if (data = 2) {value = '<span class = "label-success">' + app. localize ('pass') + '</span>';} else if (data = 3) {value = '<span class = "label-default">' + app. localize ('reobject') + '</span>';} else value = '<span class = "label-default">' + app. localize ('abandon') + '</span>'; return value ;},{ field: 'createname ', align: 'center', title: app. localize ('sendordercreator'),}, {field: 'sumcount', align: 'center', title: app. localize ('sendordertotalcount'),},]});

The following results are displayed:

Summary

The above section describes how to use the BootstrapTable component in the ABP framework. I hope it will be helpful to you. If you have any questions, please leave a message, the editor will reply to you in a timely manner. Thank you very much for your support for the help House website!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.