Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using moment.js with requireJS #2906

Closed
adrianhurt opened this issue Jul 4, 2016 · 16 comments · Fixed by #5904
Closed

Using moment.js with requireJS #2906

adrianhurt opened this issue Jul 4, 2016 · 16 comments · Fixed by #5904

Comments

@adrianhurt
Copy link

Hi, I'm trying to use chart.js and moment.js using requireJS, but I always get the following error:

Error: Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com

I can use Chart.bundle.js and it works but I can't use moment from it, so I need to import it independently.

I've tried to find any example on the web without success. And the docs says that:

The Chart.bundle.js and Chart.bundle.min.js builds include Moment.js in a single file. This version should be used if you require time axes and want a single file to include, select this version. Do not use this build if your application already includes Moment.js. If you do, Moment.js will be included twice, increasing the page load time and potentially introducing version issues.

But the examples in the repository import it twice...

<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="../../dist/Chart.bundle.js"></script>

Thanks

@etimberg
Copy link
Member

etimberg commented Jul 4, 2016

@adrianhurt is it possible to create a fiddle with this for debug purposes?

@adrianhurt
Copy link
Author

Sure!

First, I've adapted one of the examples to use RequireJS. It uses moment.js and Chart.bundle.js so moment it's imported twice:
http://codepen.io/adrianhurt/pen/ZOyKqJ

And then I've tried to change Chart.bundle to Chart but it doesn't work.
http://codepen.io/adrianhurt/pen/dXRRoL
I always get the error

Error: Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com

Even setting moment as a dependency of Chart.

I suppose I'm missing some stupid thing, but I can't find any example using RequireJS.

Thanks!

@etimberg
Copy link
Member

etimberg commented Jul 4, 2016

Looks like this is because of require. The chart factory doesn't apparently get passed the moment object returned from the factory. Since it can't find it, it defaults to window.moment which does not exist.

One solution to this would be to build using webpack or browserify since then all the dependencies would be included.

@adrianhurt
Copy link
Author

Thank you. I've noted you marked this issue as a bug, so I suppose it will be fixed. My project is now in development so meanwhile I'll use it with Chart.bundle.js and moment.js as well. Thank you for your help and for the library!

@alexciesielski
Copy link

Same problem with angular-cli (SystemJS) and Angular 2.

@freewil
Copy link

freewil commented Jul 19, 2016

It appears Chart.bundle.js does not attach moment globally to the window object?

@adrianhurt
Copy link
Author

I think it's exactly that

@hippostar
Copy link

hippostar commented Jul 27, 2016

with requireJS you would load moment.js like this

require(['moment','chartjs'], function(moment, Chart) {
    var c = new Chart(...);
});

So inside that callback, the moment object is available but not globally (window.moment). And if you try to assign it to window.moment manually inside the callback, its too late because Chartjs has already been initialized by the time we get there.

What is missing is way to pass the moment to Charts.js.

For example

require(['moment','chartjs'], function(moment, Chart) {
    // manually initialize moment
    Chart.moment = moment;
    // create charts...
    var c = new Chart(...);
});

The actual moment "object" is not used until the time scale is initialized, yet chart.js wants it to be available at initialization time?

@hippostar
Copy link

hippostar commented Aug 2, 2016

Here is a workaround for requireJS which doesn't involve modifying chartjs.

Create moment-fix.js which pre-loads moment.js and adds it to the global scope.

/*
 * moment-fix.js
 *
 * Assign reference to moment at global scope to let ChartJS use window.moment.
 */

define(['moment'], function (moment) {
    // assign moment to global window object
    window.moment = moment;
});

Setup a shim in your requireJS configuration to load moment-fix before chartjs.

require.config({
    waitSeconds: 0,
    shim: {
        'chartjs': {deps: ['lib/chartjs/moment-fix']},
        'bootstrap': {deps: ['jquery']}
    },
    paths: {
        'jquery': 'lib/jquery/jquery-2.2.3.min',
        'bootstrap': 'lib/bootstrap/bootstrap',
        'cookies': 'lib/cookie/js.cookie',
        'i18next': 'lib/i18n/i18next.amd-1.11.1.min',
        'moment': 'lib/moment/moment-config',
        'chartjs': 'lib/chartjs/Chart'
    }
});

@panzarino
Copy link
Contributor

Is this still causing an error or can this issue be closed?

@MeoMix
Copy link

MeoMix commented Oct 31, 2016

@zachpanz88 Pretty sure this issue still exists. The requirejs shim solution is alright, but making the factory pattern logic more robust still seems like the right permanent fix.

@pndewit
Copy link

pndewit commented Jun 21, 2017

Any progress on this issue? It still persists for me.

@chrisli30
Copy link

chrisli30 commented Aug 17, 2017

This problem happens to me at src/scales/scale.time.js on line 7
moment = typeof(moment) === 'function' ? moment : window.moment;
when I tried to use time series on XAxis.
Console.log the moment object I can see that moment variable is a es6Module as below, whose default is a function and what the file actually wants.
console.log(moment) -> {__esModule: true, default: ƒ}
Currently typeof(moment) === 'function' returns false and moment points to window.moment which is undefined. Hence the error "Chart.js - Moment.js could not be found!".

Solution:
Update the line in node_modules/chart.js/src/scales/scale.time.js to below works for me.
moment = typeof(moment.default) === 'function' ? moment.default : window.moment;

Comment:
I've seen this error frequently when one module "require" an es6 module in an es5 way. "Import" should work fine without the ".default". Please comment if I'm wrong.

Versions:
chart.js@2.6.0
moment@2.18.1

@daniele-sartiano
Copy link

I have the same issue of @chrisli30 with Ionic 3.

@alexciesielski
Copy link

I removed all usage of momentjs in favor of date-fns in my Angular 5 (+ angular-cli) app only to realize that Chartjs depends on Momentjs.

@itkolev
Copy link

itkolev commented Apr 2, 2018

This should've been fixed long time ago. Any progress?

@simonbrunel simonbrunel added this to the Version 2.8 milestone Dec 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.