一、引入bootstrap及bootstrap-table的css和js
我使用的是npm管理我的第三库
安装jquery、bootstrap、bootstrap-table
wenpingaodeMacBook-Pro:ci wenpingao$ npm install jquery@1.9.1
wenpingaodeMacBook-Pro:ci wenpingao$ npm install bootstrap@3.3.6
wenpingaodeMacBook-Pro:ci wenpingao$ npm install bootstrap-table
wenpingaodeMacBook-Pro:ci wenpingao$ npm install angular
wenpingaodeMacBook-Pro:ci wenpingao$ npm install angular-route
在要使用的html页面引入(我这里使用的是codeigniter 作为后台来提供数据的)
<link rel="stylesheet" type="text/css" href="<?= base_url() ?>/node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="<?= base_url() ?>/node_modules/bootstrap-table/dist/bootstrap-table.min.css">
<script type="text/javascript" src="<?= base_url() ?>/node_modules/jquery/jquery.min.js"></script>
<script type="text/javascript" src="<?= base_url() ?>/node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="<?= base_url() ?>/node_modules/bootstrap-table/dist/bootstrap-table.min.js"></script>
<script type="text/javascript" src="<?= base_url() ?>/node_modules/bootstrap-table/dist/locale/bootstrap-table-zh-CN.min.js"></script>
<script type="text/javascript" src="<?= base_url() ?>/node_modules/angular/angular.min.js"></script>
<script type="text/javascript" src="<?= base_url() ?>/node_modules/angular-route/angular-route.min.js"></script>
二、后台提供数据的Action
数据库表:
mysql root@192.168.56.103:angular> desc sys_user
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | <null> | auto_increment |
| avatar | varchar(255) | YES | | <null> | |
| account | varchar(45) | YES | | <null> | |
| password | varchar(45) | YES | | <null> | |
| salt | varchar(45) | YES | | <null> | |
| name | varchar(45) | YES | | <null> | |
| birthday | datetime | YES | | <null> | |
| sex | int(11) | YES | | <null> | |
| email | varchar(45) | YES | | <null> | |
| phone | varchar(45) | YES | | <null> | |
| roleid | varchar(255) | YES | | <null> | |
| deptid | int(11) | YES | | <null> | |
| status | int(11) | YES | | <null> | |
| createtime | datetime | YES | | <null> | |
| version | int(11) | YES | | <null> | |
+------------+--------------+------+-----+---------+----------------+
提供数据的action及model:
Model:
<?php if (!defined('BASEPATH')) {exit('No direct script access allowed');}
class UserModel extends CI_Model {
/**
* @name string 数据表名称
*/
const TABLE_NAME = 'sys_user';
/**
* @name string 主键名称
*/
const PRI_INDEX = 'id';
/**
* @name int 每页记录条数
*/
const PAGE_SIZE = 10;
public function __construct() {
parent::__construct();
//加载数据库操作类
$this->load->database();
}
/**
* [get description] 从数据库该表中查询数据
* @param [type] $where [查询条件 ,如果是数组,则拼接条件,如果是字符串或数字,查询主键是该字符串[数字]的记录,可不传,表示查询所有数据]
* @param integer $page_index [当前页数,可不传,默认为0,表示不分页,如果传入大于0的整数,可根据该数字分页查询]
* @param [type] $page_size [分页每页数,不传为上面定义的]
* @param [type] $like [搜索条件,为数组,字段=>值]
* @param [type] $order [排序条件]
* @param [type] $in [包含]
* @param [type] $notin [不包含]
* @return [type] [查询出来的结果集]
*/
public function get($where = NULL, $page_index = 0,$page_size = self::PAGE_SIZE,$like = null,$order = null,$in = null,$notin = null) {
$this->db->select('*');
$this->db->from(self::TABLE_NAME);
//条件
if ($where != null) {
if (is_array($where)) {
foreach ($where as $key => $value) {
$this->db->where($key, $value);
}
} else {
$this->db->where(self::PRI_INDEX, $where);
}
}
//模糊搜索,有个问题就是,当where条件和like同时存在时,查询的结果并不正确,原因在于需要把or like 用括号括起来,而ci框架并没有提供
//用条件组解决
if($like != null && is_array($like)){
$this->db->group_start();//开始一个新的条件组,为查询中的 WHERE 条件添加一个左括号
foreach ($like as $key => $value) {
$this->db->or_like($key, $value, 'both');
}
$this->db->group_end();//结束当前的条件组,为查询中的 WHERE 条件添加一个右括号
}
//排序
if($order != null && is_array($order)){
foreach ($order as $key => $value) {
$this->db->order_by($key,$value);
}
}
//包含
if($in != null && is_array($in)){
foreach ($in as $key => $value) {
$this->db->where_in($key, $value);
}
}
//不包含
if($notin != null && is_array($notin)){
foreach ($notin as $key => $value) {
$this->db->where_not_in($key, $value);
}
}
if ($page_index > 0) {
$this->db->limit($page_size, ($page_index-1)*$page_size);
}
$result = $this->db->get()->result();
// echo $this->db->last_query();
return $result;
}
/**
* 获取该模型类对应数据记录的分页数
* @return int 分页数
*/
public function getPageCount() {
$rowsCount = self::getRowsConut();
return ceil($rowsCount/self::PAGE_SIZE);
}
/**
* *获取该模型类对应数据表的数据总数(带查询条件)
* @return int 记录数
*/
public function getRowsConut($where = NULL,$like = null,$in = null,$notin = null) {
$this->db->select('count(*) as total ');
$this->db->from(self::TABLE_NAME);
//条件
if ($where != null) {
if (is_array($where)) {
foreach ($where as $key => $value) {
$this->db->where($key, $value);
}
} else {
$this->db->where(self::PRI_INDEX, $where);
}
}
//模糊搜索
if($like != null && is_array($like)){
$this->db->group_start();//开始一个新的条件组,为查询中的 WHERE 条件添加一个左括号
foreach ($like as $key => $value) {
$this->db->or_like($key, $value, 'both');
}
$this->db->group_end();//结束当前的条件组,为查询中的 WHERE 条件添加一个右括号
}
//包含
if($in != null && is_array($in)){
foreach ($in as $key => $value) {
$this->db->where_in($key, $value);
}
}
//不包含
if($notin != null && is_array($notin)){
foreach ($notin as $key => $value) {
$this->db->where_not_in($key, $value);
}
}
$result = $this->db->get()->result();
// echo $this->db->last_query();
return current(current($result));
}
/**
* Inserts new data into database
*
* @param Array $data Associative array with field_name=>value pattern to be inserted into database
* @return mixed Inserted row ID, or false if error ogetccured
*/
public function insert(Array $data) {
if ($this->db->insert(self::TABLE_NAME, $data)) {
return $this->db->insert_id();
} else {
return false;
}
}
/**
* Updates selected record in the database
*
* @param Array $data Associative array field_name=>value to be updated
* @param Array $where Optional. Associative array field_name=>value, for where condition. If specified, $id is not used
* @return int Number of affected rows by the update query
*/
public function update(Array $data, $where = array()) {
if (!is_array($where)) {
$where = array(self::PRI_INDEX => $where);
}
$this->db->update(self::TABLE_NAME, $data, $where);
return $this->db->affected_rows();
}
/**
* Deletes specified record from the database
*
* @param Array $where Optional. Associative array field_name=>value, for where condition. If specified, $id is not used
* @return int Number of rows affected by the delete query
*/
public function delete($where = '') {
if (is_array($where)) {
foreach ($where as $key => $value) {
$this->db->where($key, $value);
}
$this->db->delete(self::TABLE_NAME);
} else {
$this->db->delete(self::TABLE_NAME, array(self::PRI_INDEX => $where));
}
return $this->db->affected_rows();
}
}
action:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Index extends CI_Controller {
public function __construct(){
parent::__construct();
$this->load->model('UserModel','user');
$this->load->helper('url');
}
public function index() {
$this->load->view('header.php', array('title' => '主页'));
$this->load->view('index/index.php');
$this->load->view('footer.php');
}
public function list(){
//bootStrapTable 服务器端分页获取数据代码
$searchText = $this->input->get('searchText');
$sortName = $this->input->get('sortName');
$sortOrder = $this->input->get('sortOrder');
$pageSize = $this->input->get('pageSize');
$pageNumber = $this->input->get('pageNumber');
$like = NULL;
if($searchText != NULL && $searchText != ''){
$like = array('name' => $searchText,'account' => $searchText);
}
$order = NULL;
if ($sortName != NULL && $sortName != '' && $sortOrder != NULL && $sortOrder != '') {
$order = array($sortName => $sortOrder);
}
$where = NULL;
$data['rows'] = $this->user->get($where,$pageNumber,$pageSize,$like,$order);
$data['total'] = $this->user->getRowsConut($where,$like);
$data['searchText'] = $searchText;
$data['sortName'] = $sortName;
$data['sortOrder'] = $sortOrder;
$data['pageSize'] = $pageSize;
$data['pageNumber'] = $pageNumber;
$this->output->set_content_type('application/json')->set_output(json_encode($data));
}
}
/* End of file Index.php */
/* Location: ./application/controllers/Index.php */
三、bootstrapTable的使用
上面两步我们已经做好了准备工作,下面我们就开始使用bootstrapTable(这里只介绍js版的使用)
1、定义工具栏和表格主体
<div class="container" ng-app="app" ng-controller="controller">
<!-- 工具栏 -->
<div id="toolbar">
<button type="button" class="btn btn-success" ng-click="look()">
<label class="glyphicon glyphicon-eye-open"></label>
</button>
<button type="button" class="btn btn-primary" ng-click="add()">
<label class="glyphicon glyphicon-plus"></label>
</button>
</div>
<!-- 表格主体-->
<table id="table">
</table>
<!-- 提示信息-->
<div class="modal fade" id="modal-tool">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<strong>{{tool.title}}</strong> {{tool.content}}
</div>
</div>
</div>
</div>
<!-- 查看 -->
<div class="modal fade" id="modal-look">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">
{{lookUser.name}}
</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- 新增 -->
<div class="modal fade" id="modal-add">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">新增</h4>
</div>
<div class="modal-body">
<input ng-model="addUser.name" type="text" name="addUserName" id="addUserName" class="form-control" value="" required="required" pattern="" title="" placeholder="请输入姓名">
<input ng-model="addUser.gender" type="text" name="addUserGender" id="addUserGender" class="form-control" value="" required="required" pattern="" title=""· placeholder="请输入性别">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" ng-click="add_after()">Save changes</button>
</div>
</div>
</div>
</div>
</div>
2、使用JavaScript来定义bootstrapTable
var view = {
table:null,//表格对象
dataUrl:'<?= site_url('index/list')?>',//数据加载地址
delUrl:'<?= site_url('index/del')?>',//删除数据地址
selectedData:null,//选中的数据,
id:0,//操作数据的主键
defaultColumns:function () {
//表头数据列
return [
{checkbox:true},
{field:'name',title:'姓名'},
{field:'account',title:'账号',sortable:true},
{field:'createtime',title:'创建时间'},
{field:'id',title:'操作',formatter:function (argument) {
return "<a href='javascript:void(0)' onclick='view.delete("+argument+");'>删除</a>";
}}
];
},
init:function () {//初始化表格
var that = this;
this.table = $('#table').bootstrapTable({
columns:that.defaultColumns(),
classes:'table table-hover text-center',
url:that.dataUrl,
pageSize:2,//每页条数,
pageList:[5,10,20,100],//条数可选
pagination:true,//是否显示分页
sidePagination:'server',//分页方式,默认【client】,客户端分页,数据要求:json数组[{},{},{}]。为server时,数据为:[total:100,rows:[{},{},{}]],其中total为数据总量,用作分页,rows为数据数组
queryParams:function (argument) {
//console.log(argument);
return argument;
},
queryParamsType:'page',//默认为【limit】,为【limit】时,请求参数为:limit、offset、order、search、sort。否则为:pageSize, pageNumber, searchText, sortName, sortOrder
search:true,//是否显示搜索
toolbar:'#toolbar',//工具栏
responseHandler:function (argument) {
//console.log(argument);
return argument;
},
height:300,
escape:'false',//是否对富文本进行转义
searchOnEnterKey:false,//设置为 true时,按回车触发搜索方法,否则自动触发搜索方法。
searchText:'',//初始化搜索文字。
searchTimeOut:500,//毫秒,搜索超时时间
trimOnSearch:true,//搜索是否去除两边空格
clickToSelect:true,//点击行选中
showColumns:true,//是否显示内容列下拉框
showRefresh:true,//是否显示刷新按钮
});
this.initEvent();
},
initEvent:function(){
//事件
this.table.on('load-success.bs.table',function (argument) {
//加载成功时触发,其他事件请查看文档:http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/#%E4%BA%8B%E4%BB%B6
//console.log(argument);
});
},
fun:function(){
//getSelections:获取选中行
//其他方法请查看文档:http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/#%E6%96%B9%E6%B3%95
var obj = this.table.bootstrapTable('getSelections');
//console.log(obj);
},
delete:function(id){
console.log(id);
}
}
angular.module('app', ['ngRoute']).controller('controller',function ($scope) {
$scope.lookUser = {}
$scope.addUser = {
name:'',
gender:''
}
$scope.tool = {
title:'',
content:''
}
$scope.look = function(){
var obj = view.table.bootstrapTable('getSelections');
if (obj.length == 0) {
$scope.tool.title = '⚠️';
$scope.tool.content = '没有选中任何记录';
$('#modal-tool').modal();
return false;
}
if(obj.length > 1){
$scope.tool.title = '⚠️';
$scope.tool.content = '只可以选中一条记录哟';
$('#modal-tool').modal();
return false;
}
$scope.lookUser = obj[0];
// console.log($scope.lookUser);
$('#modal-look').modal();
}
$scope.add = function(){
$('#modal-add').modal();
}
$scope.add_after = function(){
console.log($scope.addUser);
$scope.addUser = {
name:'',
gender:''
}
$('#modal-add').modal('hide');
}
});
四、为了使用方便,我把使用bootstrapTable封装成sublimeText3的代码片段了,如下
<snippet>
<content><![CDATA[
${1:<!-- 引用 -->
<link rel="stylesheet" type="text/css" href="<?= base_url() ?>/node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="<?= base_url() ?>/node_modules/bootstrap-table/dist/bootstrap-table.min.css">
<script type="text/javascript" src="<?= base_url() ?>/node_modules/jquery/jquery.min.js"></script>
<script type="text/javascript" src="<?= base_url() ?>/node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="<?= base_url() ?>/node_modules/bootstrap-table/dist/bootstrap-table.min.js
"></script>
<script type="text/javascript" src="<?= base_url() ?>/node_modules/bootstrap-table/dist/locale/bootstrap-table-zh-CN.min.js"></script>}
<!-- 工具栏 -->
<div id="${2:toolbar}">
${3:<button type="button" class="btn btn-success" onclick="${5:view}.${28:fun}();">
<label class="glyphicon glyphicon-book"></label>
</button>}
</div>
<!-- 表格主体-->
<table id="${4:table}">
</table>
<!-- 表格数据处理(未完待续) -->
<script type="text/javascript">
\$(function () {
${5:view}.init();
})
var ${5:view} = {
table:null,//表格对象
dataUrl:'${6:<?= site_url('index/list')?>}',//数据加载地址
delUrl:'${7:<?= site_url('index/del')?>}',//删除数据地址
selectedData:null,//选中的数据,
id:0,//操作数据的主键
defaultColumns:function () {
//表头数据列
return [
${8:\{radio:true\},
\{field:'name',title:'姓名'\},
\{field:'account',title:'账号',sortable:true\},
\{field:'createtime',title:'创建时间'\},
\{field:'id',title:'操作',formatter:function (argument) \{
return "<a href='javascript:void(0)' onclick='view.delete("+argument+");'>删除</a>";
\}\}}
];
},
init:function () {//初始化表格
var that = this;
this.table = \$('#${4:table}').bootstrapTable({
columns:that.defaultColumns(),
classes:'${9:table table-hover text-center}',
url:that.dataUrl,
pageSize:${10:10},//每页条数,
pageList:${11:[5,10,20,100]},//条数可选
pagination:${12:true},//是否显示分页
sidePagination:'${13:server}',//分页方式,默认【client】,客户端分页,数据要求:json数组[{},{},{}]。为server时,数据为:[total:100,rows:[{},{},{}]],其中total为数据总量,用作分页,rows为数据数组
queryParams:function (argument) {
${14:console.log(argument);}
return argument;
},
queryParamsType:'${15:page}',//默认为【limit】,为【limit】时,请求参数为:limit、offset、order、search、sort。否则为:pageSize, pageNumber, searchText, sortName, sortOrder
search:${16:true},//是否显示搜索
toolbar:'#${2:toolbar}',//工具栏
responseHandler:function (argument) {
${17:console.log(argument);}
return argument;
},
height:${18:500},
escape:'${19:false}',//是否对富文本进行转义
searchOnEnterKey:${20:false},//设置为 true时,按回车触发搜索方法,否则自动触发搜索方法。
searchText:'${21:}',//初始化搜索文字。
searchTimeOut:500,//毫秒,搜索超时时间
trimOnSearch:${22:true},//搜索是否去除两边空格
showColumns:${29:true},//是否显示内容列下拉框
showRefresh:${30:true},//是否显示刷新按钮
clickToSelect:${23:true},//点击行选中${24:
ignoreClickToSelectOn:function (argument) \{
//点击单元格事件,返回false,取消事件
${25:console.log(argument);}
\}}
});
this.initEvent();
},
initEvent:function(){
//事件
${26:this.table.on('load-success.bs.table',function (argument) {
//加载成功时触发,其他事件请查看文档:http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/#%E4%BA%8B%E4%BB%B6
${27:console.log(argument);}
\});}
},
${28:fun}:function(){
//getSelections:获取选中行
//其他方法请查看文档:http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/#%E6%96%B9%E6%B3%95
var obj = this.table.bootstrapTable('getSelections');
console.log(obj);
}
}
$0
</script>
]]></content>
<!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
<tabTrigger>bst</tabTrigger>
<!-- Optional: Set a scope to limit where the snippet will trigger -->
<scope>text.html</scope>
<description>bootstrapTable</description>
</snippet>