Reputation: 9295
I would like to make moment to be injectable through out my app.
I just started learning ng2 and couldn't find this type of usage in the docs.
Here is what I have in my app.module.ts
:
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {HttpModule} from '@angular/http';
import {AppComponent} from './app.component';
import * as moment from 'moment';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [{provide: 'moment', useValue: moment}],
bootstrap: [AppComponent]
})
export class AppModule {
}
and here is the component:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.sass']
})
export class AppComponent {
title = 'app works!';
constructor(private moment) {
this.title += this.moment;
}
}
there is this error:
Uncaught Error: Can't resolve all parameters for AppComponent:
How should this be done correctly?
UPDATED MODULE
const moment = new OpaqueToken('moment');
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [{provide: moment, useValue: moment}],
bootstrap: [AppComponent]
})
export class AppModule {
}
UPDATED COMPONENT
import { Component } from '@angular/core';
import * as moment from 'moment';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.sass']
})
export class AppComponent {
title = 'app works!';
constructor(private moment: moment) {
this.title += this.moment()
}
}
There is an error on this line constructor(private moment: moment)
which tells that: Cannot find name 'moment'.
Upvotes: 4
Views: 2410
Reputation: 1143
Not sure if this helps now but you need something similar (not tested) to the following to make it work in your service.
import { Inject } from '@angular/core';
constructor(@Inject(moment) private moment) {
this.title += this.moment()
}
The key bit is the @Inject
Upvotes: 0
Reputation: 7379
The best workaround that I have come to find is to create a wrapper service, but also expose some of the most common methods directly on the service itself using getters:
import { Injectable } from '@angular/core';
import * as moment from 'moment';
/**
* A wrapper for the moment library
*/
@Injectable()
export class MomentService {
/**
* Creates and returns a new moment object with the current date/time
*/
public moment() { return moment(); }
// expose moment properties directly on the service
public get utc() { return moment.utc; }
public get version() { return moment.version; }
public get unix() { return moment.unix; }
public get isMoment() { return moment.isMoment; }
public get isDate() { return moment.isDate; }
public get isDuration() { return moment.isDuration; }
public get now() { return moment.now; }
}
Upvotes: 0
Reputation: 5092
Moment by itself is not an injectable for Angular2. However it can be wrapped inside one.
moment.service.ts
import { Injectable } from '@angular/core';
import * as m from 'moment';
@Injectable()
export class MomentService {
moment = m;
}
app.module.ts
import { MomentService } from './moment.service';
@NgModule({
providers: [MomentService]
...
app.component.ts
import { MomentService } from './moment.service';
export class AppComponent {
constructor(private ms: MomentService){
console.log('Moment:' + this.ms.moment("20111031", "YYYYMMDD").toString());
}
}
Not perfect, but works.
Upvotes: 4
Reputation: 11525
If you are loading moment.js so it is available globally how about wrapping it with a service which you can then inject throughout your app?
import {Moment} from '../../node_modules/moment';
import { Injectable } from '@angular/core';
declare var moment: any;
@Injectable()
export class MomentService {
constructor() { }
get(): Moment {
return moment;
}
}
I this way you get the TS IntelliSense when you are coding (at least I do in VSCode) and you can handle mocking moment for testing easily too.
Upvotes: 0
Reputation: 136174
You need to use OpaqueToken
which will allowed you to create a string based token. I'd just suggest you to change the name of moment
to avoid thr collision with moment
variable of library.
// You can place this is some file, so that you can export it.
export const Moment = new OpaqueToken('moment');
and then you could use
providers: [{provide: MomentStatic, useClass: moment}],
You can go through this article for more details
While using dependency include it in a Component constructor.
constructor(private moment: MomentStatic)
Upvotes: 3
Reputation: 10834
Moment doesn't have to be injected, it is a library that you can "just use". It's enough to import it in your typescript file now you can use moment's features.
Upvotes: 0