When running the following code as-is, it get this error:
Uncaught TypeError: Cannot read property 'TYPE_CAMPAIGN' of undefined
Plunker Example
entity.service.ts
import {Injectable} from '@angular/core';
import {CampaignService} from './campaign/campaign.service';
import {TagService} from './tag/tag.service';
@Injectable()
export class EntityService {
static TYPES = [
CampaignService.TYPE_CAMPAIGN,
TagService.TYPE_TAG
];
}
campaign.service.ts
import {Injectable} from '@angular/core';
import {EntityService} from '../entity.service';
@Injectable()
export class CampaignService {
static TYPE_CAMPAIGN = 'campaign';
constructor(private entityService: EntityService) {}
public getTypes() {
return EntityService.TYPES;
}
}
tag.service.ts
import {Injectable} from '@angular/core';
import {EntityService} from '../entity.service';
@Injectable()
export class TagService {
static TYPE_TAG = 'tag';
constructor(private entityService: EntityService) {}
}
However, when I remove the constructor from campaign.service.ts, the code works without issue. Why does the error occur, and how do I access static properties when the constructor is included?
Update 1: After testing using Angular's Injector to offset when classes are loaded, I find that I still have an issue accessing static properties of EntityService inside methods of CampaignService. I've also found that adding private entityService: EntityService in campaign.service.ts causes the issue.
Update 2: The issue is caused by the order of import statements in the Module that is providing the services (I recently alphabetized my import statements).
app.module.ts
import {CampaignService} from './campaign/campaign.service';
import {EntityService} from '../entity.service';
import {TagService} from './tag/tag.service';
@NgModule({
providers: [
CampaignService,
EntityService,
TagService
]
});
When the import statement for entity.service.ts is moved before campaign.service.ts, both CampaignService and TagService are able to work without issue.
Update 3: It looks like the issue is version specific. Here is the example of the issue happening in the version I am currently using: Example
If you switch the import statements in src/app.component.ts while watching the console, then you will see the issue at hand.
It may be the injector decides there's a circular reference. Looking at the code, I would not expect it since only one service has a constructor. However, the behavior you describe points to this.
You can try injecting the injector and delaying the injection process by a tick.
See Angular2: 2 services depending on each other
@Injectable()
export class CampaignService {
static TYPE_CAMPAIGN = 'campaign';
private entityService;
constructor(injector: Injector) {
setTimeout(() => this.entityService = injector.get(EntityService));
}
}
Hopefully this covers your use-case. Here's my StackBlitz
campaign.service.ts
import {Injectable, Injector} from '@angular/core';
import {EntityService} from './entity.service';
@Injectable()
export class CampaignService {
static TYPE_CAMPAIGN = 'campaign';
private entityService;
types = EntityService.TYPES;
constructor(private injector: Injector) {
setTimeout( () => this.entityService = injector.get(EntityService) );
}
}
app.component.ts
import { Component } from '@angular/core';
import {EntityService} from './entity.service';
import {CampaignService} from './campaign.service';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular 5';
types = EntityService.TYPES;
constructor(
private entityService: EntityService,
private campaignService: CampaignService
) { }
}
app.component.html
<hello name="{{ name }}"></hello>
<p>
Start editing to see some magic happen :)
</p>
<div> Types from EntityService {{ types }} </div>
<div> Types from campaignService {{ campaignService.types }} </div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With