使用 NodeJS 和 MySql 的 jQuery 数据表

问题描述 投票:0回答:3

我想显示数据表中的值。我打开 chrome 开发工具并转到网络选项卡、XHR,问题是,响应是一个 HTML 文档

服务器端代码:

router.get('/agents', (req, res) => {
  let dB = req.dB;
  let sql = 'SELECT * FROM tbl_users WHERE role_id = 3';

  dB.query(sql, (err, agents) => {
    if (err) throw err;
    const data = { agents };
    console.log(data);

    res.render('dashboard/agents', data);
  });
});

客户端脚本:

$('#agent_table').DataTable( {
  processing: true,
  serverSide: true,
  ajax: {
    url: '/administrator/agents',
    type: 'GET',
    dataSrc: 'agents'
  },
  columns: [
    { data: 'user_id' },
    { data: 'checked' },
    { data: 'first_name' },
    { data: 'middle_name' },
    { data: 'role_id' },
  ]
} );

客户端htmlt:

<table id="agent_table" class="table table-striped table-bordered dt-responsive nowrap"
            cellspacing="0" width="100%">
            <thead>
              <tr>
                <th>User ID</th>
                <th>
                  <div class="checkbox checkbox-success select_all">
                    <input class="styled" type="checkbox" id="check_all">
                    <label for="check_all" class="check_all_label">All</label>
                  </div>
                </th>
                <th>First Name</th>
                <th>Middle Name</th>
                <th>Last Name</th>
                <th>Role</th>
              </tr>
            </thead>
          </table>

控制台登录服务器

{ 代理:[ RowDataPacket { 用户 ID:6, 名字:'帕梅拉', middle_name: '珍珠', 姓氏:'萨贝斯', 电子邮件:'[电子邮件受保护]', 密码: '1bd07c9db7ae63c02f2ee75471727f58', 手机号码: '09503713607', 邀请代码: '', 生日: '2005 年 11 月 29 日', 性别女', 地址: '', 图像:空, 联络人: '', contact_person_number: '', 角色 ID:3, 经度: '', 纬度: '', 医疗信息:'', 已验证:1, 已删除:0, 创建时间:'0000-00-00 00:00:00', 更新时间:2018-05-30T20:42:43.000Z } ] }

mysql node.js ajax datatables server-side-rendering
3个回答
2
投票

我认为问题在于你对 res.render 的使用。因为根据明确的文档 res.render() 函数会编译您的模板,在其中插入本地变量,并从这两个内容中创建 html 输出并将其发送。所以试试这个。

res.json(data)


0
投票

var url = req.protocol + '://' + req.get('host');

var draw = req.body.draw;
var row = req.body.start;
var count = 1+parseInt(row);
var rowperpage = req.body.length; // Rows display per page
//var columnIndex = req.query.order[0]['column']; // Column index
//console.log(req.body.search);
var dataArr = [];

adminTagModel.CountTagsAll(dataArr, function (totalRecordsValid)
{
    var tagDataobj = {
        row : row,
        rowperpage : rowperpage
    };
    adminTagModel.showTagsAll(tagDataobj, function (totalValid)
    {
        for (var i = 0; i < totalValid.length; i++) 
        {
            dataArr.push({  'count' : count++ ,'tag_name' : totalValid[i].tag_name,'action' : "<a href='"
                +url+"/admin/tagdetails/"+totalValid[i].t_id+"' target='_blank'  ><i class='fa fa-eye'  alt='View Detail'></i></a>"});
        }

        var response = {
            "draw" : draw,
            "iTotalRecords" : totalRecordsValid[0].allcount,
            "iTotalDisplayRecords" : totalRecordsValid[0].allcount,
            "aaData" : dataArr
        };
        res.send(response);
        return response;
    });

0
投票

我最近开发了一个轻量级库来简化 Node.js 中 jQuery 数据表的服务器端处理。它提供对 MySQL 和 Sequelize 的支持:)

图书馆代码

    class SSP {

    static getData(request, userSqlQuery, columns) {
        this.request = request.body;

        this.userSqlQuery = userSqlQuery;

        this.columns = columns;
        this.replacements = {};
        this.whereString = '';

        this.orderData = this.order();
        this.limitData = this.limit();

        this.dbcolumns = this.pluck(this.columns, 'db');

        this.selectColumns = (this.dbcolumns).map((e, i) => {
            return "`" + e + "`";
        }).join(',');


        return this;
    }


    static async sequelize(connection) {
        let finalRecord = {};

        this.filter('sequelize');

        let finalQuery = `SELECT SQL_CALC_FOUND_ROWS ${this.selectColumns} FROM (${this.userSqlQuery}) as temp ${this.whereString} ${this.orderData} ${this.limitData}`;

        try {
            const dbData = await connection.query(
                finalQuery,
                {
                    replacements: this.replacements,
                    type: connection.QueryTypes.SELECT
                }
            );

            const resFilterLength = (await connection.query('SELECT FOUND_ROWS()', {
                type: connection.QueryTypes.SELECT
            }));

            const recordsFiltered = resFilterLength[0]['FOUND_ROWS()'] ?? 0;

            const resTotalLength = await connection.query(`SELECT COUNT(*) as datatable_ssp_count FROM (${this.userSqlQuery}) AS temp`, {
                type: connection.QueryTypes.SELECT
            });

            const recordsTotal = resTotalLength[0]['datatable_ssp_count'] ?? 0;

            finalRecord.draw = parseInt(this.request.draw);
            finalRecord.recordsTotal = parseInt(recordsTotal);
            finalRecord.recordsFiltered = parseInt(recordsFiltered);

            const mappedData = await this.mapDbToDToColumn(this.columns, dbData);

            finalRecord.data = mappedData;

            return finalRecord;

        } catch (error) {
            console.error("Error in sequelize:", error);
            return null;
        }
    }

    static async mysql(connection) {
        let finalRecord = {};

        this.filter('mysql');

        let finalQuery = `SELECT SQL_CALC_FOUND_ROWS ${this.selectColumns} FROM (${this.userSqlQuery}) as temp ${this.whereString} ${this.orderData} ${this.limitData}`;

        try {
            const [dbData, fields] = await connection.query(finalQuery, this.replacements);
            const [resFilterLength, resFilterLengthfields] = await connection.query("SELECT FOUND_ROWS()");
            const recordsFiltered = resFilterLength[0]['FOUND_ROWS()'] ?? 0;
            const resTotalLength = await connection.query(`SELECT COUNT(*) as datatable_ssp_count FROM (${this.userSqlQuery}) AS temp`);
            const recordsTotal = resTotalLength[0][0].datatable_ssp_count ?? 0;

            finalRecord.draw = parseInt(this.request.draw);
            finalRecord.recordsTotal = parseInt(recordsTotal);
            finalRecord.recordsFiltered = parseInt(recordsFiltered);

            const mappedData = await this.mapDbToDToColumn(this.columns, dbData);

            finalRecord.data = mappedData;

            return finalRecord;

        } catch (error) {
            console.error("Error in Mysql:", error);
            return null;
        }

    }

    static async mapDbToDToColumn(columns, data) {
        var out = [];

        for (var i = 0, ien = data.length; i < ien; i++) {
            var row = {};

            for (var j = 0, jen = columns.length; j < jen; j++) {
                var column = columns[j];

                if (typeof column.formatter === 'function') {
                    var formatterResult = column.formatter(data[i][column.db], data[i]) || null;
                    if (formatterResult instanceof Promise) {
                        if (column.dt !== undefined) {
                            row[column.dt] = await formatterResult || null;
                        } else {
                            row[column.db] = await formatterResult || null;
                        }
                    } else {
                        if (column.dt !== undefined) {
                            row[column.dt] = formatterResult;
                        } else {
                            row[column.db] = formatterResult;
                        }
                    }
                } else {
                    if (column.dt !== undefined) {
                        row[column.dt] = data[i][columns[j].db];
                    } else {
                        row[column.db] = data[i][columns[j].db];
                    }
                }
            }
            out.push(row);
        }
        return out;
    }

    static filter(mode) {

        let request = this.request;
        let columns = this.columns;

        let globalSearch = [];

        let columnSearch = [];

        let dtColumns = columns.map(column => column.dt);

        if (mode === 'mysql') {
            this.replacements = [];
        }

        if (request.search && request.search.value !== '') {
            let str = request.search.value;

            for (let i = 0; i < request.columns.length; i++) {
                let requestColumn = request.columns[i];
                let columnIdx = dtColumns.indexOf(requestColumn.data);
                columnIdx = (columnIdx <= -1) ? 0 : columnIdx;
                
                let column = columns[columnIdx];

                if (requestColumn.searchable === 'true' || requestColumn.searchable === true) {

                    if (mode === 'sequelize') {
                        let binding = `ssp_search_value_${i}`;
                        globalSearch.push("`" + column.db + "` LIKE :" + binding);
                        this.replacements[binding] = `%${str}%`;
                    } else if (mode === 'mysql') {
                        globalSearch.push("`" + column.db + "` LIKE ?");
                        (this.replacements).push(`%${str}%`);
                    }
                }
            }
        }

        // Individual column filtering
        for (let i = 0; i < request.columns.length; i++) {
            let requestColumn = request.columns[i];
            let columnIdx = dtColumns.indexOf(requestColumn.data);

            columnIdx = (columnIdx <= -1) ? 0 : columnIdx;

            let column = columns[columnIdx];
            let str = requestColumn.search.value;

            if ((requestColumn.searchable === 'true' || requestColumn.searchable === true) && str !== '') {
                if (mode === 'sequelize') {
                    let binding2 = `ssp_search_value2_${i}`;
                    columnSearch.push("`" + column.db + "` LIKE :" + binding2);
                    let dynamicBindings2 = [];
                    dynamicBindings2.push({
                        key: binding2,
                        value: `%${str}%`
                    })
                } else if (mode === 'mysql') {
                    columnSearch.push("`" + column.db + "` LIKE ?");
                    this.replacements.push(`%${str}%`);
                }
            }
        }

        this.whereString = '';

        if (globalSearch.length > 0) {
            this.whereString = '(' + globalSearch.join(' OR ') + ')';
        }

        if (columnSearch.length > 0) {
            this.whereString = this.whereString === '' ?
                columnSearch.join(' AND ') :
                this.whereString + ' AND ' + columnSearch.join(' AND ');
        }

        if (this.whereString !== '') {
            this.whereString = 'WHERE ' + this.whereString;
        }

    }

    static order() {
        let columns = this.columns;
        let order = '';
        let request = this.request;
        if (request.order && request.order.length > 0) {
            let orderBy = [];
            let dtColumns = columns.map(column => (column.dt ?? column.db));

            for (let i = 0, ien = request.order.length; i < ien; i++) {
                // Convert the column index into the column data property
                let columnIdx = parseInt(request.order[i].column);
                let requestColumn = request.columns[columnIdx];
                columnIdx = dtColumns.indexOf(requestColumn.data);
                let column = columns[columnIdx];

                if (requestColumn.orderable === 'true' || requestColumn.orderable === true) {
                    let dir = request.order[i].dir === 'asc' ? 'ASC' : 'DESC';

                    orderBy.push('`' + column.db + '` ' + dir);
                }
            }

            order = 'ORDER BY ' + orderBy.join(', ');
        }

        return order;
    }

    static limit() {

        let start = this.request.start ?? 0;
        let length = this.request.length ?? 0;
        let limit = '';

        if (start !== undefined && length != -1) {
            limit = "LIMIT " + parseInt(start) + ", " + parseInt(length);
        }
        return limit;
    }

    static pluck(arrayOfObjects, key) {
        return arrayOfObjects.map(obj => obj[key]);
    }
}

export default SSP;

控制器中的使用

import { mysqlConn, sequelize } from '../config/database.js';

class UserController {

    // Usage in Controller
    async listdata(req, res) {
        let column = [  //column to select database columns
            {
                'db': 'name', // column name in database
                'dt': 'name', // column name in datatable
                'formatter': function (data, rowData) {  // (For data formatting )optional
                    return `${data} (${rowData.email})`; // example
                }
            },
            {
                'db': 'email',
                'dt': 'email',

            },
            {
                'db': 'id',
            }
        ];

        let resultSequelize = await (SSP.getData(req, 'select * from users', column)).sequelize(sequelizeConn); // sequelizeConn is sequelize connection instance

        // OR

        let resultMysql = await (SSP.getData(req, 'select * from users', column)).mysql(mysqlConn); // sequelizeConn is mysql connection instance
        res.status(200).json(result);
    }
}

查看文件

<div class="container">
    <table id="usersTable" class="display" style="width:100%">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Email</th>
            </tr>
        </thead>
        <tbody>

        </tbody>
    </table>
</div>

<script>
    $('#usersTable').DataTable({
        "lengthMenu": [[5, 25, 50, -1], [5, 25, 50, "All"]],
        processing: true,
        serverSide: true,
        ajax: {
            url: '/list',
            type: 'post',
        },
        columns: [
            { data: 'id' },
            { data: 'name' },
            { data: 'email' },
        ]
    });
</script>
© www.soinside.com 2019 - 2024. All rights reserved.