如何在Angular 2 TypeScript应用程序中使用moment.js库?


231

我试图将其与打字稿绑定一起使用:

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

test.ts:

import {moment} from 'moment/moment';

没有:

npm install moment --save

test.ts:

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

但是,当我调用moment.format()时,出现错误。应该很简单,有人可以提供行之有效的命令行/导入组合吗?


1
请分享您的错误
basarat

1
如果我安装moment.d.ts并使用导入,则会在... / typings / browser / ambient / moment / moment.d.ts(9,21)中出现编译错误:错误TS2503:找不到命名空间“ moment” 。而且,如果我不安装类型输入并使用require,我会得到Uncaught TypeError:moment.format不是一个函数
Sergey Aldoukhov,2016年

这里有太多旧答案了。请在这里查看:github.com/angular/angular-cli/wiki/…–
Didia

3
Hinrich的答案对我来说适用于ng4(截至2017年6月)stackoverflow.com/a/43257938/1554495
里脊

SergeyAldoukhov仍然是最佳答案?当然,@ Hinrich's是吗?
jenson-button-event

Answers:


513

2017年4月更新:

从2.13.0版开始,Moment包含一个打字稿定义文件。https://momentjs.com/docs/#/use-it/typescript/

只需在控制台类型中使用npm安装

npm install --save moment

然后在您的Angular应用中,导入就像这样简单:

import * as moment from 'moment';

就这样,您将获得TypeScript的全面支持!

奖励编辑:要像MomentTypescript中一样键入变量或属性,可以执行以下操作:

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

1
将其添加到您的app.module文件并导入数组是否重要?还是可以简单地将其导入组件中并使用它?
凯瑟琳R

3
@Katherine R您可以在任何文件中使用它,它不是Angular专用的。
辛里奇

现在,瞬间插件又如何呢?
Greywire

2
实际上,此答案不是特定于Angular的,它适用于任何Typescript项目。
辛里奇

太好了,如何在模板上使用管道?
vladanPro

98

moment是第三方全球资源。当对象存在于window浏览器中时。因此,import在您的angular2应用程序中它不正确。而是<script>在您的html中包含标记,以加载moment.js文件。

为了让TypeScript开心,您可以添加

declare var moment: any;

在您使用它停止编译错误的文件顶部,也可以使用

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

或使用tsd安装TypeScript可能自己找到的moment.d.ts文件。

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');
}

只需确保在您的html中添加脚本标签,否则将不存在。

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

模块加载 moment

首先,您需要设置一个模块加载器(例如System.js)以加载当下的commonjs文件

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

然后将时刻导入文件中需要使用的地方

import * as moment from 'moment';

要么

import moment = require('moment');

编辑:

有些捆绑程序(例如Webpack或SystemJS builder或Browserify)也有一些选项,可以使您远离窗口对象。有关这些的更多信息,请访问各自的网站以获取指导。


3
这是可能的,但是非常冗长,因为您需要在模块的模块加载器(例如System,现在的commonjs节点版本中加载),然后才能使用import * as moment from 'moment';import moment = require('moment');在所有意图和目的上都相同的引用它,但是确实需要打字稿中的一些细微差别。
SnareChops

@SnareChops typings install moment --ambient -- save不会typings下拉定义文件并创建对///<reference path="./path/to/moment.d.ts" />?的引用。我在运行时遇到相同的错误npm run tsc
Shawn Northrop

这具有误导性;import时刻没有错。
斯蒂格勒16-3-29

2
这个答案是不完整的,因为您必须使用打字来管理力矩定义。另外,它不需要导入任何内容。请看下面我的回答
贝尔纳多·帕切科

8
这个答案具有误导性,moment是一个全局变量这一事实并不意味着您“必须”将其作为脚本标签加载。如果使用某种捆绑程序(Webpack),则可以并且应该将其捆绑在供应商文件中。如果使用webpack和正确的加载程序,也可以解决全局分配问题。
Shlomi Assaf

49

以下对我有用。

首先,暂时安装类型定义。

typings install moment --save

(注意:NOT --ambient

然后,要解决缺少适当的出口的问题:

import * as moment from 'moment';

2
我不得不import moment from "moment";改为使其工作。
Aetherix '16

3
这个答案是不完整的,因为您不需要导入任何内容。请看下面我的回答
贝尔纳多·帕切科

1
同样,离子2 beta /角2 rc的每次迭代似乎都带来了一种导入事物的新方法,因此您可能不得不尝试其中一些建议,即使它们曾经是最新的答案
Discodane

import * as moment from 'moment';是关键。
nima

我在注册表中找不到“ moment”(“ npm”)。whenI安装尝试定义,帮助请
塞巴斯蒂安·罗哈斯

28

我会选择以下内容:

npm install moment --save

systemjs.config.js文件map数组中添加:

'moment': 'node_modules/moment'

packages数组添加:

'moment': { defaultExtension: 'js' }

在您的component.ts中使用: import * as moment from 'moment/moment';

就是这样。您可以在组件的类中使用:

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


25

我们现在正在使用模块,

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

npm install angular2-moment

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


76
这还不够,因为这只会安装管道。显然,您无法以这种方式在模块中使用“转折日期”。
ntaso

1
很想如何在组件类使用angular2矩过滤器的一些技巧
trickpatty

3
这应该是:从'angular2-moment / moment.module'导入{MomentModule};
yasser

1
这不再是选择的答案。看看@Hinrich的答案。 npm install moment --savenpm install @types/moment --save stackoverflow.com
questions/35166168/…

而不是安装包装纸,它应该像是import * as moment from 'moment';
M. Atif Riaz

22

要在Typescript项目中使用它,您需要安装一下:

npm install moment --save

安装时刻.ts后,导入后可以在任何文件中使用它:

import * as moment from "moment";


1
注意** @ types / moment @ 2.13.0:这是Moment的存根类型定义(github.com/moment/moment)。Moment提供了自己的类型定义,因此您不需要安装@ types / moment!
温尼马卡

1
大!这里的官方参考:momentjs.com/docs
Andrea

14

-更新11/01/2017

现在不推荐使用Typings,而已将其替换为npm @types。从现在开始,除了npm之外,不需要其他任何工具即可进行类型声明。要使用Moment,您不需要通过@types安装类型定义,因为Moment已经提供了自己的类型定义。

因此,它减少到仅三个步骤:

1-安装时刻,包括类型定义:

npm install moment --save

2-在您的HTML文件中添加脚本标签:

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

3-现在您可以使用它。期。

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

---原始答案

只需3个步骤即可完成此操作:

1-安装力矩定义- * .d.ts文件:

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

2-在您的HTML文件中添加脚本标签:

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

3-现在您可以使用它。期。

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

我在dt可用的打字版本上遇到麻烦。它使用的是即时的旧版本,没有我要使用的新方法。如果我按照他们的建议(momentjs.com/docs/#/use-it/system-js)做,则该应用程序会编译,但不会在浏览器中加载。我快要走到死路了……
Fabricio

我无法使script标签与angular cli一起使用。比导入更有意义
Winnemucca

@Bernardo我尝试按照您的步骤操作,并安装了moment.js。之后declare var moment;然而,分型是不是为我工作。键入后moment().没有智能感知。我想我在这里缺少一些步骤。
Shyamal Parikh

相当确定这行不通,Web Pack如何知道将其包含在构建节点模块中?
约翰尼

12

对于Angular 7+(也支持8和9)

1:通过命令安装时刻 npm install moment --save

2:请勿在 app.module.ts

3:只需在您的component文件或其他任何文件的顶部添加import语句,如下所示:import * as moment from 'moment';

4:现在您可以moment在代码中的任何地方使用。就像:

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


我必须这样输入: import * as moment_ from 'moment'; const moment = moment_;否则我会得到Error: Cannot call a namespace ('moment')
Snook

很奇怪听。moment_只是一个字面名称。我想这可以是任何东西...
Rahmat Ali

1
请注意,import * as moment from 'moment';将捆绑包的大小增加约500kb。有一篇很好的文章介绍了解决方案medium.jonasbandi.net/…
Kosmonaft

9

使用ng CLI

> npm install moment --save

在app.module中

import * as moment from 'moment';

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

在组件中

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

这样,您可以一次导入时刻

UPDATE Angular => 5

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

对我来说,与aot和通用产品一起工作

我不喜欢使用任何东西,但使用瞬间。

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

Parameter 'moment' implicitly has an 'any' type出错了。
方位角

这在产品模式下对您有用吗?在开发人员模式下运行正常,但是当我在生产模式下运行应用程序时,它失败了。我的应用程序也有延迟加载的模块(以防万一)。片刻最终为空。
jbgarr

@jbgarr我已经在像构造函数这样的惰性模块中尝试过(@Inject('moment')private moment){console.log('date',moment()); }没有问题
Whisher

8

angular2-moment库具有类似{{myDate | amTimeAgo}}用于.html文件。

这些相同的管道也可以在组件类(.ts)文件中作为Typescript函数进行访问。首先按照说明安装该库:

npm install --save angular2-moment

现在,在node_modules / angular2-moment中将是“ .pipe.d.ts”文件,例如calendar.pipe.d.tsdate-format.pipe.d.ts等。

其中每个都包含等效管道的Typescript函数名称,例如,DateFormatPipe()amDateFormatPipe的函数。

要在项目中使用DateFormatPipe,请在app.module.ts中将其导入并添加到全局提供程序中:

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

然后在要使用该函数的任何组件中,将其导入顶部,注入到构造函数中并使用:

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

要使用任何功能,请遵循以下过程。如果有一种方法可以访问所有功能,那就太好了,但是以上解决方案都不适合我。


非常感谢!随时随地为angular2演示向您展示如何仅在模板上使用它。您的非常有帮助的帖子向我展示了在将其输出到模板之前如何使用它来操纵值。
安德鲁·少年·霍华德

@royappa我看到有些使用Pipes模块,有些仅用片刻时间在Typescript中访问它。我了解您是说您可以在Typescript中使用Pipes版本,但是同时安装这两个版本有何危害?
雅克

5

如果您可以添加更多的第三方软件包,则可以使用angular2-moment库。安装非常简单,您应该按照README上的最新说明进行操作。我还安装了打字

对我而言,它就像是一种魅力,几乎没有添加任何代码即可使其正常工作。


5

不知道这是否仍然是人们的问题,但是...使用SystemJS和MomentJS作为库,这为我解决了问题

/*
 * 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;

从那里对我来说很好。


5

对于angular2 RC5这对我有用...

通过npm首次安装

npm install moment --save

然后将时刻导入您要使用的组件中

import * as moment from 'moment';

最后在systemjs.config.js中的“ map”和“ 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'}
  };

关于webpack的等效步骤有什么想法?
巴拉特·吉莱达

@BharatGeleda无需使用webpack进行任何操作。使用Angular2和angular-cli,我只需要npm安装并导入它。由于一刻的最新版本支持打字稿,因此我不需要任何打字。
Stanislasdrg恢复莫妮卡

1
使我导入另一个语言环境的唯一解决方案:import 'moment/locale/de.js';谢谢!
iBaff

4

除了SnareChop的答案外,我还必须更改momentjs的类型文件。

moment-node.d.ts我替换:

export = moment;

export default moment;


4

我自己在Angular中使用Moment的版本

npm i moment --save

import * as _moment from 'moment';

...

moment: _moment.Moment = _moment();

constructor() { }

ngOnInit() {

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

}

首先将as导入_moment,然后声明moment类型_moment.Moment为初始值为的变量_moment()

普通导入的矩不会给您任何自动完成功能,但是如果您要从通过调用矩命名空间初始化的包中的命名空间中声明类型Moment接口的矩_moment'moment'_moment()您自动完成矩的api。

我认为@types typings,如果您正在寻找自动的自动完成的矩型javascript库的话,这是不使用或角度提供程序的最即时的方式。


安装类型将使您可以访问自动完成功能:npm install @types/moment --save
jamesjansson

3

尝试添加"allowSyntheticDefaultImports": true到您的中tsconfig.json

旗是做什么的?

这基本上告诉TypeScript编译器可以使用ES6 import语句,即

import * as moment from 'moment/moment';

在未声明默认导出的CommonJS模块(如Moment.js)上。该标志仅影响类型检查,而不影响生成的代码。

如果将SystemJS用作模块加载器,则很有必要。如果您告诉TS编译器您使用SystemJS,则该标志将自动打开:

"module": "system"

如果将IDE配置为使用,这还将删除IDE引发的任何错误tsconfig.json


2

对于与systemjs和jspm的angular2必须做的:

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();

2

对于ANGULAR CLI用户

在此处的文档中使用外部库:

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

只需通过安装您的库

npm install lib-name --save

并将其导入您的代码中。如果该库不包含类型,则可以使用以下命令进行安装:

npm install lib-name --save

npm install @ types / lib-name --save-dev

然后打开src / tsconfig.app.json并将其添加到类型数组:

“ types”:[“ lib-name”]

如果您为其添加类型的库仅在e2e测试中使用,请使用e2e / tsconfig.e2e.json。单元测试和src / tsconfig.spec.json也是如此。

如果该库在@ types /处没有可用的类型,您仍然可以通过手动为其添加类型来使用它:

首先,在src /文件夹中创建Types.d.ts文件。

该文件将自动包含为全局类型定义。然后,在src / typings.d.ts中,添加以下代码:

声明模块'typeless-package';

最后,在使用该库的组件或文件中,添加以下代码:

从typeless-package导入*作为typelessPackage;typelessPackage.method();

做完了 注意:您可能需要或发现有用的方法是为尝试使用的库定义更多类型。


如果您需要逐步说明,请查看本文。medium.com/@jek.bao.choo/...
wag0325

1

我遵循建议使用System来允许allowSyntheticDefaultImports(因为从现在起就没有导出可用)。然后我按照某人的建议使用:

import moment from 'moment';

时刻被映射到我的system.js配置中。由于某种原因,其他导入语句对我不起作用


这是目前的最后答案,但唯一有效的答案!
TJL

1

以下为我工作:

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

时刻节点在类型存储库中不存在。您需要重定向到Definitely Typed,以使其使用前缀dt起作用。


1

使用systemjs,我要做的是,在systemjs.config中,我添加了 moment

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

然后你就可以轻松地导入moment只是做

import * as moment from 'moment'

1

我知道这是一个旧线程,但是对我来说,最有效的最简单的解决方案是:

  1. 首先安装 npm install moment --save
  2. 在我的组件中,需要使用node_modules并使用它:
const moment = require('../../../node_modules/moment/moment.js');

@Component({...})
export class MyComponent {
   ...
   ngOnInit() {
       this.now = moment().format();
   }
   ...
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.