使用DataTables.net-bs

时间:2017-01-27 18:51:41

标签: javascript angular datatables

我目前正在使用Angular 2编写应用程序并将其配置为使用DataTables.net,DataTables.net-bs和DataTables.net-select。

在大多数情况下,一切看起来都很棒。除了一个例外,应用程序的分页显示,好像没有应用样式。

我在浏览器中检查了源代码,并应用了默认的类和HTML结构:

<div class="dataTables_paginate paging_full_numbers" id="myTable_paginate">
    <a tabindex="0" class="paginate_button first disabled" id="myTable_first" aria-controls="myTable" data-dt-idx="0">First</a>
    <a tabindex="0" class="paginate_button previous disabled" id="myTable_previous" aria-controls="myTable" data-dt-idx="1">Previous</a>
    <span>
        <a tabindex="0" class="paginate_button current" aria-controls="myTable" data-dt-idx="2">1</a>
        <a tabindex="0" class="paginate_button " aria-controls="myTable" data-dt-idx="3">2</a>
        <a tabindex="0" class="paginate_button " aria-controls="myTable" data-dt-idx="4">3</a>
        <a tabindex="0" class="paginate_button " aria-controls="myTable" data-dt-idx="5">4</a>
        <a tabindex="0" class="paginate_button " aria-controls="myTable" data-dt-idx="6">5</a>
        <span class="ellipsis">…</span>
        <a tabindex="0" class="paginate_button " aria-controls="myTable" data-dt-idx="7">580</a>
    </span>
    <a tabindex="0" class="paginate_button next" id="myTable_next" aria-controls="myTable" data-dt-idx="8">Next</a>
    <a tabindex="0" class="paginate_button last" id="myTable_last" aria-controls="myTable" data-dt-idx="9">Last</a>
</div>

链接的功能起作用,它在显示器上看起来很丑陋,因为我使用的是DataTables Bootstrap CSS,而且它没有使用无序列表输出相应的HTML。我在浏览器中进入了调试器,并且正在加载DataTables.net-bs的代码。我在JavaScript中添加了一堆断点,并且正在调用工厂方法。但是,它似乎再也没有被调用过。

以下是我的vendors.browser.ts

的相关代码
require('datatables.net')();
require('datatables.net-bs')();
require('datatables.net-select')();
require('file-saver');

我也关闭了AMD,因为我知道这对某些人来说是一个问题。以下是webpack.common.js文件的相关代码:

    {
      test: /datatables\.net.*/,
      loader: 'imports?define=>false'
    },

另外,另一个插件Datatables.net-select功能正常。

如果我无法解决这个问题,我可以使用DataTables.net-dt中包含的样式,但我更愿意让它正常工作。

有没有人对正在发生的事情有任何潜在的想法?

2 个答案:

答案 0 :(得分:4)

将datatables.net集成到ANGULAR 4 CLI的步骤

我们需要将 datatables.net 安装为全局库(适用于所有组件)。这意味着该库不会延迟加载,而是在第一页加载时导入/下载。

经过2天的研究和大量深入研究Angular CLI后,我能够使用最新版本的CLI(1.1.3)和Angular 4

这些是wiki中帮助我的相关文章:

https://github.com/angular/angular-cli/wiki/stories-global-scripts

https://github.com/angular/angular-cli/wiki/stories-third-party-lib

  1. 安装JQuery及其打字

    npm install --save jquery
    npm install --save-dev @types/jquery
    
  2. 安装datatables.net及其打字

    npm install --save datatables.net
    npm install --save-dev @types/datatables.net
    
  3. [可选]添加datatables.net主题(bootstrap主题)

    npm install --save datatables.net-bs
    
  4. [可选]添加datatables.net扩展名(选择,按钮等)

    npm install --save datatables.net-select
    npm install --save datatables.net-select-bs
    npm install --save-dev @types/datatables.net-select
    
  5. 现在让我们配置一下,这样我们就可以让编译器理解这些库,并在编译时不要出错。 打开tsconfig.app.json并在types节点下添加以下类型:

    "types": [
        "YOUR_OTHER_TYPINGS_HERE",
        "jquery",
        "datatables.net",
        "datatables.net-select"
    ]
    
  6. 最后,我们需要将我们的库添加到全局脚本和样式部分。 打开tsconfig.app.json文件并更新stylesscripts部分,如下所示:

    "styles": [
        "YOUR_OTHER_CSS_HERE",
        "../node_modules/bootstrap/dist/css/bootstrap.css",
        "../node_modules/datatables.net-bs/css/dataTables.bootstrap.css",
        "../node_modules/datatables.net-select-bs/css/select.bootstrap.css",
        "YOUR_OTHER_CSS_HERE"
    ],
    "scripts": [
        "YOUR_OTHER_JS_LIBS_HERE",
        "../node_modules/jquery/dist/jquery.js",
        "../node_modules/bootstrap/dist/js/bootstrap.js",
        "../node_modules/datatables.net",
        "../node_modules/datatables.net-bs/js/dataTables.bootstrap.js",
        "../node_modules/datatables.net-select/js/dataTables.select.js",
        "YOUR_OTHER_JS_LIBS_HERE",
    ],
    

    只需确保正确设置库的顺序,如果在中间添加库,这并不重要。但基本上你需要JQuery,然后是Bootstrap,然后是datatables.net,最后需要你可能需要的任何datatables.net扩展或插件。

  7. 请注意,应该将几乎任何其他JQuery插件导入Angular 4 CLI项目。

    现在您可以在组件中使用数据表,如下所示:

    import { Component, OnInit, Input, Output, EventEmitter, ElementRef } from '@angular/core';
    import { Shipment } from '../../models';
    
    @Component({
        selector: 'shipment-list',
        template: `
            <table id="shipments_table" class="table table-striped table-bordered table-hover no-footer">
            </table>
        `,
        styleUrls: ['./shipment-list.component.css']
    })
    export class ShipmentListComponent implements OnInit {
        private shipmentsTable: any;
        private tableWidget: any;
        @Input() shipments: Shipment[];
        // Event Emmiter for when the user selects a row
        @Output() shipmentSelected: EventEmitter<Shipment> = new EventEmitter();
        constructor(
            private el: ElementRef // You need this in order to be able to "grab" the table element form the DOM 
        ) { }
    
        public ngOnInit() {
            this.loadShipments();
        }
        public loadShipments(): void {
            if (this.tableWidget) {
                this.tableWidget.destroy(); // essentially refreshes the table
                // you can also remove all rows and add new
                // this.tableWidget.clear().rows.add(this.shipments).draw();
            }
            let tableOptions: any = {
                data: this.shipments,
                dom: 'rt',
                select: true,
                columns: [
                    { title: 'Content', data: 'content' },
                    { title: 'Packages', data: 'packages' },
                    { title: 'Weight', data: 'weight' }
                ]
            }
            this.shipmentsTable = $(this.el.nativeElement.querySelector('table'));
            this.tableWidget = this.shipmentsTable.DataTable(tableOptions);
            this.tableWidget.on('select', (e, dt, type, indexes) => {
                // I DIDN'T TRY THIS IN HERE...Just debug it and check the best way to emit an actual object
                this.shipmentSelected.emit(this.shipments[indexes[0]]);
            });
        }
    }
    

答案 1 :(得分:1)

我解决了这个问题。

问题在于此代码:

require('datatables.net')();
require('datatables.net-bs')();
require('datatables.net-select')();
require('file-saver');

问题出在DataTables.net模块开头的检查范围内。在每个模块的顶部,您有以下内容:

(function( factory ){
    if ( typeof define === 'function' && define.amd ) {
        // AMD
        define( ['jquery', 'datatables.net'], function ( $ ) {
            return factory( $, window, document );
        } );
    }
    else if ( typeof exports === 'object' ) {
        // CommonJS
        module.exports = function (root, $) {
            if ( ! root ) {
                root = window;
            }

            if ( ! $ || ! $.fn.dataTable ) {
                // Require DataTables, which attaches to jQuery, including
                // jQuery if needed and have a $ property so we can access     the
                // jQuery object that is used
                $ = require('datatables.net')(root, $).$;
            }

            return factory( $, root, root.document );
        };
    }
    else {
        // Browser
        factory( jQuery, window, document );
    }

使用上面的代码,我们不会传入全局$变量。第一次导入运行时,$ variable为null,因此它会适当地设置值。第二次导入时,传入的值为null,它将与插件的扩展一起重置。当第三次导入运行时,我们遇到了同样的问题。现在有选择功能,但我们覆盖了Bootstrap插件的功能。

因此,更正后的代码如下:

require('datatables.net')(window, $);
require('datatables.net-bs')(window, $);
require('datatables.net-select')(window, $);
require('file-saver');

我的代码基于此:{https://github.com/brakmic/Angular2-Articles/blob/master/article6/src/init/vendor.ts][1]

window.$ = window.jQuery = require('jquery');
require('bootstrap-loader');
require('datatables.net')();
require('datatables.net-bs')();
require('datatables.net-buttons')();

我的打字稿编辑器正在第一行进行抨击,所以我删除了它并没有完全理解幕后发生的事情。经验教训。