Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using datatables with angular + webpack + es6

I can't seem to make use of the javascript libraries for DataTables (or any external bootstrap javascript for that matter. Import Angular works fine).

This is what I have in my app.js file.

import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min.js';
import 'datatables.net/js/jquery.dataTables';
import 'datatables.net-bs/css/dataTables.bootstrap.css';
import 'datatables.net-bs/js/dataTables.bootstrap';
import './assets/css/styles.css';

import angular from 'angular';
import uirouter from 'angular-ui-router';
import routing from './app.config';
import dashboard from './dashboard';

angular.module('app', [uirouter, dashboard])
  .config(routing);

and my webpack.config.js file:

var webpack = require('webpack');
var path = require('path');
var OpenBrowserPlugin = require('open-browser-webpack-plugin');

module.exports = {
  entry: [
    'webpack/hot/dev-server',
    path.resolve(__dirname, 'app/app.js')
  ],
  output: {
    path: __dirname + '/build',
    publicPath: '/',
    filename: './bundle.js'
  },
  module: {
    loaders:[
      { test: /\.html$/, exclude: /node_modules/, loader: 'html' },
      { test: /\.css$/, loader: 'style-loader!css-loader' },
      { test: /\.js?$/, include: path.resolve(__dirname, 'app'), exclude: /node_modules/, loader: 'babel-loader' },
      { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
            { test: /\.(woff|woff2)$/, loader:"url?prefix=font/&limit=5000" },
            { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
            { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml" }
    ]
  },
  resolve: {
    root: path.join(__dirname, 'app'),
    extensions: ['', '.js', '.css'],
    modulesDirectories: ['app', 'node_modules']
  },
  plugins: [
    new OpenBrowserPlugin({ url: 'http://localhost:8080' }),
    new webpack.ProvidePlugin({
     $: "jquery",
     jQuery: "jquery"
   })
  ]
};

I'm not getting any errors about not being able to find these javascript files I am trying to import (bootstrap.min.js, dataTables.bootstrap.js, etc), however it doesn't seem to be using them.

In my html file that's supposed to be using the datatable, it looks like it's only pulling from the css, and nothing is being applied to it from the javascript files.

<div class="col-lg-12">
    <div class="panel panel-default">
        <div class="panel-heading">
            DataTables Advanced Tables
        </div>
        <!-- /.panel-heading -->
        <div class="panel-body">
            <div class="dataTables_wrapper">
                <table class="table table-striped table-bordered table-hover" id="dataTables-example">
                    <thead>
                        <tr>
                            <th>Rendering engine</th>
                            <th>Browser</th>
                            <th>Platform(s)</th>
                            <th>Engine version</th>
                            <th>CSS grade</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr class="odd gradeX">
                            <td>Trident</td>
                            <td>Internet Explorer 4.0</td>
                            <td>Win 95+</td>
                            <td class="center">4</td>
                            <td class="center">X</td>
                        </tr>
                        <tr class="even gradeC">
                            <td>Trident</td>
                            <td>Internet Explorer 5.0</td>
                            <td>Win 95+</td>
                            <td class="center">5</td>
                            <td class="center">C</td>
                        </tr>
                        <tr class="odd gradeA">
                            <td>Trident</td>
                            <td>Internet Explorer 5.5</td>
                            <td>Win 95+</td>
                            <td class="center">5.5</td>
                            <td class="center">A</td>
                        </tr>
                        <tr class="even gradeA">
                            <td>Trident</td>
                            <td>Internet Explorer 6</td>
                            <td>Win 98+</td>
                            <td class="center">6</td>
                            <td class="center">A</td>
                        </tr>
                        <tr class="odd gradeA">
                            <td>Trident</td>
                            <td>Internet Explorer 7</td>
                            <td>Win XP SP2+</td>
                            <td class="center">7</td>
                            <td class="center">A</td>
                        </tr>
                        <tr class="even gradeA">
                            <td>Trident</td>
                            <td>AOL browser (AOL desktop)</td>
                            <td>Win XP</td>
                            <td class="center">6</td>
                            <td class="center">A</td>
                        </tr>
                        <tr class="gradeA">
                            <td>Gecko</td>
                            <td>Firefox 1.0</td>
                            <td>Win 98+ / OSX.2+</td>
                            <td class="center">1.7</td>
                            <td class="center">A</td>
                        </tr>
                        <tr class="gradeA">
                            <td>Gecko</td>
                            <td>Firefox 1.5</td>
                            <td>Win 98+ / OSX.2+</td>
                            <td class="center">1.8</td>
                            <td class="center">A</td>
                        </tr>
                        <tr class="gradeA">
                            <td>Gecko</td>
                            <td>Firefox 2.0</td>
                            <td>Win 98+ / OSX.2+</td>
                            <td class="center">1.8</td>
                            <td class="center">A</td>
                        </tr>
                        <tr class="gradeA">
                            <td>Gecko</td>
                            <td>Firefox 3.0</td>
                            <td>Win 2k+ / OSX.3+</td>
                            <td class="center">1.9</td>
                            <td class="center">A</td>
                        </tr>
                        <tr class="gradeA">
                            <td>Gecko</td>
                            <td>Camino 1.0</td>
                            <td>OSX.2+</td>
                            <td class="center">1.8</td>
                            <td class="center">A</td>
                        </tr>
                        <tr class="gradeA">
                            <td>Gecko</td>
                            <td>Camino 1.5</td>
                            <td>OSX.3+</td>
                            <td class="center">1.8</td>
                            <td class="center">A</td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- /.table-responsive -->
        </div>
        <!-- /.panel-body -->
    </div>
    <!-- /.panel -->
</div>
</div>

Am I missing something here? It's hard to find solutions for this online as not many people seem to be using Angular with ES6 and Webpack.

like image 258
ant0n Avatar asked Dec 07 '15 19:12

ant0n


2 Answers

This drove me crazy, so hopefully this helps a bit...basically, I ended up importing everything through NPM as I could, then manually otherwise. See this site for some specifications on what modules are needed:

http://datatables.net/download/npm

After working through it, it's does seem like the Webpack/ES6/bundling style is not on-par with how code like React (or possibly Angular 2) works.

First, this code was based off of the NG6-Angular/Webpack/ES6 starter. Here is the app.js file...slighty trimmed:

import angular from 'angular';
import 'angular-flot';
import 'angular-datatables';
import 'angular-breadcrumb';
import 'angular-sweetalert';
import 'datatables.net-bs';
import 'flot';
import ngAnimate from 'angular-animate';
import ngCookies from 'angular-cookies';
import ngFileUpload from 'ng-file-upload';
import ngResource from 'angular-resource';
import ngSanitize from 'angular-sanitize';
import ngTouch from 'angular-touch';
import 'restangular';
import satellizer from 'satellizer';
import toastr from 'angular-toastr';
import uiBootstrap from 'angular-bootstrap-npm';
import uiRouter from 'angular-ui-router';
import 'angular-ui-router-title';
import 'api-check';
import './externals';

import Common from './common/common';
import Components from './components/components';
import component from './app.component';
import AppRun from  './app.run';
import AppConfig from  './app.config';

const nameNormalized = 'app';

angular
    .module(nameNormalized, [
        'angular-flot',
        'datatables',
        'datatables.bootstrap',
        'datatables.buttons',
        'formly',
        'formlyBootstrap',
        'ncy-angular-breadcrumb',
        ngAnimate,
        ngCookies,
        ngFileUpload,
        ngResource,
        ngSanitize,
        ngTouch,
        'oitozero.ngSweetAlert',
        'restangular',
        satellizer,
        toastr,
        uiBootstrap,
        'ui.footable',
        uiRouter,
        'ui.router.title',
        Common.name,
        Components.name
    ])
    .config(AppConfig)
    .directive(nameNormalized, component())
    .run(AppRun)
;

And here is the externals file that gets imported above:

import 'script!../node_modules/api-check/dist/api-check.min.js';
import 'script!../node_modules/angular-formly/dist/formly.min.js';
import 'script!../node_modules/angular-formly-templates-bootstrap/dist/angular-formly-templates-bootstrap.min.js';
import 'imports?jQuery=jquery!../node_modules/metismenu/dist/metisMenu.min.js';
import 'imports?$=jquery!../bower_components/angular-footable/src/angular-footable.js';
import 'imports?$=jquery!../bower_components/angular-footable/src/angular-footable.js';
import 'imports?$=jquery!../bower_components/flot.tooltip/js/jquery.flot.tooltip.min.js';
import 'imports?$=jquery!../bower_components/jquery.flot.time.js/index.js';
import 'imports?$=jquery!./externals/jquery.ba-resize.js';
import 'imports?jQuery=jquery!./externals/jquery.flot.resize.js';
import 'imports?$=jquery!./externals/inspinia.js';

And here is the Webpack config...it's not stripped down, but maybe that's preferred:

import autoprefixer from 'autoprefixer';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import path from 'path';
import webpack from 'webpack';
import _ from 'lodash';

let plugins = [
    new webpack.NoErrorsPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.ProvidePlugin({
        _: 'lodash',
        $: 'jquery',
        jQuery: 'jquery',
        'window.jQuery': 'jquery',
        'window.$': 'jquery'
    }),
    new CopyWebpackPlugin([
        {from: './assets/img/favicons', to: 'assets/img/favicons'}
    ])
];

let cssMinimize = '';
let htmlMinify = {};
let extractStyles = false;

if(process.env.NODE_ENV === 'production') {
    /*
        Production uglify disabled for now:
        https://github.com/webpack/webpack/issues/1079
        https://github.com/webpack/webpack/pull/560#issuecomment-66818521
        Possible workaround for future:
        https://www.npmjs.com/package/uglify-loader
        plugins.push(new webpack.optimize.UglifyJsPlugin({
            compress: {warnings: true},
            sourceMap: false,
            mangle: false,
            exclude: [/bower_components/, /node_modules/]
        }));
    */

    htmlMinify = {
        removeComments: true,
        collapseWhitespace: true,
        conservativeCollapse: true,
        preserveLineBreaks: false,
        keepClosingSlash: true
    };

    cssMinimize = 'minimize';
}

module.exports = o => ({
    context: path.join(__dirname, '/src'),
    entry: {app: getEntry(o)},
    eslint: {configFile: './.eslintrc'},
    module: {
        loaders: [
            {
                test: /.(png|woff(2)?|eot|ttf|svg)(\?[a-z0-9=\.]+)?$/,
                loader: 'url?limit=1000000'
            },
            {
                test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|xml|ico)$/,
                loader: 'file?name=[path][name].[ext]'
            },
            {test: /\.json$/, loader: 'json'},
            {
                test: /\.js$/,
                loader: 'ng-annotate!babel?presets[]=es2015,presets[]=stage-0',
                exclude: [/bower_components/, /node_modules/]
            },
            {
                test: /\.js$/,
                loader: 'eslint',
                exclude: [/bower_components/, /node_modules/]
            },
            {
                test: /\.styl$/,
                loader: getStyleLoader(_.merge({extra: '!stylus'}, o))
            },
            {
                test: /\.less$/,
                loader: getStyleLoader(_.merge({extra: '!less'}, o))
            },
            {
                test: /\.css$/,
                loader: getStyleLoader(_.merge({extra: ''}, o))
            },
            {
                test: /\.html$/,
                loader: 'ngtemplate?relativeTo=' +
                    (path.resolve(__dirname, '/src')) + '/!html'
            }
        ]
    },
    output: {
        path: path.join(__dirname, '/dist'),
        publicPath: '/',
        filename: '[name].js'
    },
    plugins: getPlugins(o),
    postcss: [autoprefixer({browsers: ['last 2 versions']})]
});

function getStyleLoader(o) {
    const ending = 'css?' + cssMinimize + '!postcss' + o.extra;

    if(o.watch) {
        return 'style!' + ending;
    } else {
        return ExtractTextPlugin.extract('style', ending);
    }
}

function getPlugins(o) {
    if(!o.watch) {
        plugins.push(new ExtractTextPlugin('[name].css'));
    } else {
        plugins.push(new webpack.HotModuleReplacementPlugin());
    }

    plugins.push(new HtmlWebpackPlugin({
       filename: 'index.html',
       hash: true,
       minify: htmlMinify,
        template: './src/index.html',
        title: 'oa',
        watch: o.watch
    }));

    return plugins;
}

function getEntry(o) {
    let entry = ['./app'];

    if(o.watch) {
        entry.push('webpack/hot/dev-server');
    }

    return entry;
}

Lastly, the package.json dependencies

"dependencies": {
    "angular": "~1.4.7",
    "angular-animate": "~1.4.7",
    "angular-bootstrap-npm": "^0.14.3",
    "angular-breadcrumb": "^0.4.1",
    "angular-cookies": "^1.4.8",
    "angular-datatables": "^0.5.2",
    "angular-flot": "0.0.15",
    "angular-formly": "^7.3.5",
    "angular-formly-templates-bootstrap": "^6.1.7",
    "angular-resource": "~1.4.7",
    "angular-route": "~1.4.7",
    "angular-sanitize": "^1.4.8",
    "angular-sweetalert": "^1.1.0",
    "angular-toastr": "^1.6.0",
    "angular-touch": "^1.4.8",
    "angular-ui-router": "~0.2.15",
    "angular-ui-router-title": "0.0.4",
    "angular-ui-sortable": "~0.13.4",
    "api-check": "^7.5.5",
    "autoprefixer": "^6.1.0",
    "babel-core": "^6.1.21",
    "babel-eslint": "^4.1.5",
    "babel-loader": "^6.2.0",
    "babel-preset-es2015": "^6.1.18",
    "babel-preset-stage-0": "^6.1.18",
    "bootstrap": "^3.3.6",
    "bower": "^1.7.1",
    "copy-webpack-plugin": "^0.3.3",
    "css-loader": "^0.22.0",
    "datatables.net": "^1.10.10",
    "datatables.net-bs": "^1.10.10",
    "datatables.net-buttons": "^1.1.0",
    "datatables.net-buttons-bs": "^1.1.0",
    "drmonty-datatables-responsive": "^1.0.6",
    "eslint": "^1.9.0",
    "eslint-loader": "^1.1.1",
    "extract-text-webpack-plugin": "^0.9.1",
    "file-loader": "^0.8.5",
    "flot": "^0.8.0-alpha",
    "gulp": "^3.9.0",
    "gulp-rename": "^1.2.2",
    "gulp-template": "^3.1.0",
    "gulp-util": "^3.0.7",
    "html-loader": "^0.4.0",
    "html-webpack-plugin": "^1.7.0",
    "imports-loader": "^0.6.5",
    "jquery": "^2.1.4",
    "json-loader": "^0.5.4",
    "less": "^2.5.3",
    "less-loader": "^2.2.2",
    "loader-utils": "^0.2.12",
    "lodash": "^3.10.1",
    "metismenu": "^2.2.0",
    "ng-annotate-loader": "0.0.10",
    "ng-file-upload": "^10.1.5",
    "ngtemplate-loader": "^1.3.1",
    "path": "^0.12.7",
    "postcss-loader": "^0.8.0",
    "raw-loader": "^0.5.1",
    "restangular": "^1.5.1",
    "satellizer": "^0.13.1",
    "script-loader": "^0.6.1",
    "source-map": "^0.5.3",
    "style-loader": "^0.13.0",
    "stylus-loader": "^1.4.2",
    "url-loader": "^0.5.7",
    "webpack": "^1.12.6",
    "webpack-dev-server": "^1.12.1",
    "yargs": "^3.30.0"
  }
like image 89
David Sinclair Avatar answered Nov 12 '22 10:11

David Sinclair


I also needed to require every file, paying attention to extra files not automatically loaded.

Package.json

"dependencies": {
    "angular": "~1.5.8",
    "angular-datatables": "^0.5.5",
    "datatables.net": "^1.10.12",
    "datatables.net-bs": "^1.10.12",
    "datatables.net-buttons": "^1.2.2",
    "datatables.net-buttons-bs": "^1.2.2",
    "jquery": "~3.1.1",
}

core.module.js

import 'jquery';    //jQuery has to be load before AngularJS
import angular from 'angular';

import 'angular-datatables';
import 'datatables.net';
import 'datatables.net-bs';
import 'datatables.net-buttons';
import 'datatables.net-buttons-bs';
import 'datatables.net-buttons/js/buttons.colVis';
import 'datatables.net-buttons/js/buttons.flash';
import 'datatables.net-buttons/js/buttons.html5';
import 'datatables.net-buttons/js/buttons.print';
import 'angular-datatables/dist/plugins/buttons/angular-datatables.buttons';

import 'datatables.net-bs/css/dataTables.bootstrap.css';
import 'datatables.net-buttons-bs/css/buttons.bootstrap.css';

angular.module(MODULE_NAME, [
    'datatables',
    'datatables.bootstrap',
    'datatables.buttons',
]);

Posted to provide a clearer response.

like image 43
McGiogen Avatar answered Nov 12 '22 09:11

McGiogen