How to use moment.js library in angular 2 typescript app?

TypescriptAngular

Typescript Problem Overview


I tried to use it with typescript bindings:

npm install moment --save
typings install moment --ambient -- save

test.ts:

import {moment} from 'moment/moment';

And without:

npm install moment --save

test.ts:

var moment = require('moment/moment');

But when I call moment.format(), I get an error. Should be simple, can anybody provide a command line/import combination that would work?

Typescript Solutions


Solution 1 - Typescript

Update April 2017:

As of version 2.13.0, Moment includes a typescript definition file. https://momentjs.com/docs/#/use-it/typescript/

Just install it with npm, in your console type

npm install --save moment

And then in your Angular app, import is as easy as this:

import * as moment from 'moment';

That's it, you get full Typescript support!

Bonus edit: To type a variable or property as Moment in Typescript you can do this e.g.:

let myMoment: moment.Moment = moment("someDate");

Solution 2 - Typescript

moment is a third party global resource. The moment object lives on window in the browser. Therefor it is not correct to import it in your angular2 application. Instead include the <script> tag in your html that will load the moment.js file.

To make TypeScript happy you can add

declare var moment: any;

at the top of your files where you use it to stop the compilation errors, or you can use

///<reference path="./path/to/moment.d.ts" />

or use tsd to install the moment.d.ts file which TypeScript might find on it's own.

Example

import {Component} from 'angular2/core';
declare var moment: any;

@Component({
    selector: 'example',
    template: '<h1>Today is {{today}}</h1>'
})
export class ExampleComponent{
    today: string = moment().format('D MMM YYYY');
}

Just be sure to add the script tag in your html or moment won't exist.

<script src="node_modules/moment/moment.js" />

Module loading moment

First you would need to setup a module loader such as System.js to load the moment commonjs files

System.config({
    ...
    packages: {
        moment: {
            map: 'node_modules/moment/moment.js',
            type: 'cjs',
            defaultExtension: 'js'
        }
    }
});

Then to import moment into the file where needed use

import * as moment from 'moment';

or

import moment = require('moment');

EDIT:

There are also options with some bundlers such as Webpack or SystemJS builder or Browserify that will keep moment off of the window object. For more information on these, please visit their respective websites for instruction.

Solution 3 - Typescript

The following worked for me.

First, install the type definitions for moment.

typings install moment --save

(Note: NOT --ambient)

Then, to work around the lack of a proper export:

import * as moment from 'moment';

Solution 4 - Typescript

I would go with following:

npm install moment --save

To your systemjs.config.js file's map array add:

'moment': 'node_modules/moment'

to packages array add:

'moment': { defaultExtension: 'js' }

In your component.ts use: import * as moment from 'moment/moment';

and that's it. You can use from your component's class:

today: string = moment().format('D MMM YYYY');

Solution 5 - Typescript

We're using modules now,

try import {MomentModule} from 'angular2-moment/moment.module';

after npm install angular2-moment

http://ngmodules.org/modules/angular2-moment

Solution 6 - Typescript

To use it in a Typescript project you will need to install moment:

npm install moment --save

After installing moment, you can use it in any .ts file after importing it:

import * as moment from "moment";

Solution 7 - Typescript

For Angular 7+ (Also Supports 8, 9, 10, 11):

1: Install moment by command npm install moment --save

2: Do not add anything in the app.module.ts

3: Just add import statement in top of your component or any other file like this: import * as moment from 'moment';

4: Now you can use moment anywhere in your code. Just like:

myDate = moment(someDate).format('MM/DD/YYYY HH:mm');

Solution 8 - Typescript

--- Update 11/01/2017

Typings is now deprecated and it was replaced by npm @types. From now on getting type declarations will require no tools apart from npm. To use Moment you won't need to install the type definitions through @types because Moment already provides its own type definitions.

So, it reduces to just 3 steps:

1 - Install moment which includes the type definitions:

npm install moment --save

2 - Add the script tag in your HTML file:

<script src="node_modules/moment/moment.js" />

3 - Now you can just use it. Period.

today: string = moment().format('D MMM YYYY');

--- Original answer

This can be done in just 3 steps:

1 - Install moment definition - *.d.ts file:

typings install --save --global dt~moment dt~moment-node

2 - Add the script tag in your HTML file:

<script src="node_modules/moment/moment.js" />

3 - Now you can just use it. Period.

today: string = moment().format('D MMM YYYY');

Solution 9 - Typescript

with ng CLI

> npm install moment --save

in app.module

import * as moment from 'moment';

providers: [{ provide: 'moment', useValue: moment }]

in component

constructor(@Inject('moment') private moment)

this way you import moment once

UPDATE Angular => 5

{
   provide: 'moment', useFactory: (): any => moment
}

For me works in prod with aot and also with universal

I dont like using any but using moment.Moment I got

Error	Typescript	Type 'typeof moment' is not assignable to type 'Moment'. Property 'format' is missing in type 'typeof moment'.

Solution 10 - Typescript

The angular2-moment library has pipes like {{myDate | amTimeAgo}} to use in .html files.

Those same pipes can also be accessed as Typescript functions within a component class (.ts) file. First install the library as instructed:

npm install --save angular2-moment

In the node_modules/angular2-moment will now be ".pipe.d.ts" files like calendar.pipe.d.ts, date-format.pipe.d.ts and many more.

Each of those contains the Typescript function name for the equivalent pipe, for example, DateFormatPipe() is the function for amDateFormatPipe.

To use DateFormatPipe in your project, import and add it to your global providers in app.module.ts:

import { DateFormatPipe } from "angular2-moment";
.....
providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}, ...., DateFormatPipe]

Then in any component where you want to use the function, import it on top, inject into the constructor and use:

import { DateFormatPipe } from "angular2-moment";
....
constructor(.......,  public dfp: DateFormatPipe) {
	let raw = new Date(2015, 1, 12);
	this.formattedDate = dfp.transform(raw, 'D MMM YYYY');
}

To use any of the functions follow this process. It would be nice if there was one way to gain access to all the functions, but none of the above solutions worked for me.

Solution 11 - Typescript

If you're okay adding more third-party packages, I used the angular2-moment library. Installation was pretty straightforward, and you should follow the latest instructions on the README. I also installed typings as a result of this.

Worked like a charm for me, and barely added any code to get it working.

Solution 12 - Typescript

Not sure if this is still an issue for people, however... Using SystemJS and MomentJS as library, this solved it for me

/*
 * Import Custom Components
 */
import * as moment from 'moment/moment'; // please use path to moment.js file, extension is set in system.config

// under systemjs, moment is actually exported as the default export, so we account for that
const momentConstructor: (value?: any) => moment.Moment = (<any>moment).default || moment;

Works fine from there for me.

Solution 13 - Typescript

for angular2 RC5 this worked for me...

first install moment via npm

npm install moment --save

Then import moment in the component that you want to use it

import * as moment from 'moment';

lastly configure moment in systemjs.config.js "map" and "packages"

// map tells the System loader where to look for things
  var map = {
  ....
  'moment':                     'node_modules/moment'
  };
  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    ...
    'moment':                       { main:'moment', defaultExtension: 'js'}
  };

Solution 14 - Typescript

In addition to SnareChop's answer, I had to change the typings file for momentjs.

In moment-node.d.ts I replaced:

export = moment;

with

export default moment;

Solution 15 - Typescript

Moment.js now supports TypeScript in v2.14.1.

See: https://github.com/moment/moment/pull/3280

Solution 16 - Typescript

My own version of using Moment in Angular

npm i moment --save

import * as _moment from 'moment';

...

moment: _moment.Moment = _moment();

constructor() { }

ngOnInit() {

    const unix = this.moment.format('X');
    console.log(unix);    

}

First import moment as _moment, then declare moment variable with type _moment.Moment with an initial value of _moment().

Plain import of moment wont give you any auto completion but if you will declare moment with type Moment interface from _moment namespace from 'moment' package initialized with moment namespace invoked _moment() gives you auto completion of moment's api's.

I think this is the most angular way of using moment without using @types typings or angular providers, if you're looking auto completion for vanilla javascript libraries like moment.

Solution 17 - Typescript

Try adding "allowSyntheticDefaultImports": true to your tsconfig.json.

What does the flag do?

This basically tells the TypeScript compiler that it's okay to use an ES6 import statement, i. e.

import * as moment from 'moment/moment';

on a CommonJS module like Moment.js which doesn't declare a default export. The flag only affects type checking, not the generated code.

It is necessary if you use SystemJS as your module loader. The flag will be automatically turned on if you tell your TS compiler that you use SystemJS:

"module": "system"

This will also remove any errors thrown by IDEs if they are configured to make use of the tsconfig.json.

Solution 18 - Typescript

The following worked for me:

typings install dt~moment-node --save --global

The moment-node does not exist in typings repository. You need to redirect to Definitely Typed in order to make it work using the prefix dt.

Solution 19 - Typescript

for angular2 with systemjs and jspm had to do:

import * as moment_ from 'moment';
export const moment =  moment_["default"];

var a = moment.now();
var b = moment().format('dddd');
var c = moment().startOf('day').fromNow();

Solution 20 - Typescript

For ANGULAR CLI users

Using external libraries is in the documentation here:

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

> Simply install your library via > > > npm install lib-name --save > > and import it in your code. If the library does not include typings, > you can install them using: > > npm install lib-name --save > > > npm install @types/lib-name --save-dev > > Then open src/tsconfig.app.json and add it to the types array: > > > "types":[ "lib-name" ] > > If the library you added typings for is only to be used on your e2e > tests, instead use e2e/tsconfig.e2e.json. The same goes for unit tests > and src/tsconfig.spec.json. > > If the library doesn't have typings available at @types/, you can > still use it by manually adding typings for it: > > First, create a typings.d.ts file in your src/ folder. > > This file will be automatically included as global type definition. > Then, in src/typings.d.ts, add the following code: > > declare module 'typeless-package'; > > Finally, in the component or file that uses the library, add the > following code: > > import * as typelessPackage from 'typeless-package'; > > typelessPackage.method(); > > Done. Note: you might need or find useful to define more typings for > the library that you're trying to use.

Solution 21 - Typescript

I followed advice to allow allowSyntheticDefaultImports (since there is no export from moment to use for me), using System. Then I followed someone's advice to use:

import moment from 'moment';

With moment being mapped in my system.js config. The other import statements wouldn't work for me, for some reason

Solution 22 - Typescript

With systemjs what I did is, inside my systemjs.config I added map for moment

map: {
   .....,
   'moment': 'node_modules/moment/moment.js',
   .....
}

And then you can easily import moment just by doing

import * as moment from 'moment'

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSergey AldoukhovView Question on Stackoverflow
Solution 1 - TypescriptHinrichView Answer on Stackoverflow
Solution 2 - TypescriptSnareChopsView Answer on Stackoverflow
Solution 3 - TypescriptStigglerView Answer on Stackoverflow
Solution 4 - TypescriptAleksandrasView Answer on Stackoverflow
Solution 5 - TypescriptFalcon78View Answer on Stackoverflow
Solution 6 - TypescriptShahzadView Answer on Stackoverflow
Solution 7 - TypescriptRahmat AliView Answer on Stackoverflow
Solution 8 - TypescriptBernardo PachecoView Answer on Stackoverflow
Solution 9 - TypescriptWhisherView Answer on Stackoverflow
Solution 10 - TypescriptroyappaView Answer on Stackoverflow
Solution 11 - TypescriptwliView Answer on Stackoverflow
Solution 12 - TypescriptAstrid KarstenView Answer on Stackoverflow
Solution 13 - TypescriptArni GudjonssonView Answer on Stackoverflow
Solution 14 - TypescriptjevensonView Answer on Stackoverflow
Solution 15 - TypescriptsivabudhView Answer on Stackoverflow
Solution 16 - Typescriptflyingpluto7View Answer on Stackoverflow
Solution 17 - TypescriptMark LangerView Answer on Stackoverflow
Solution 18 - TypescriptstvnwrgsView Answer on Stackoverflow
Solution 19 - Typescriptborn2netView Answer on Stackoverflow
Solution 20 - TypescriptSomView Answer on Stackoverflow
Solution 21 - TypescriptPaul Jerome BordalloView Answer on Stackoverflow
Solution 22 - TypescriptPankaj ParkarView Answer on Stackoverflow