Reputation: 12483
EDIT: a lot of this question was deleted as it became less relevant as I found out more about the problem.
I get this error in the console:
Error in app/find-page/find-page.component.html:1:3 caused by: No provider for ShopService!
The place where I use ShopService is in another Service called ResultService. How do I declare a provider for ShopService in ResultService? Because when I add ShopService to the providers of the only module in the app (appModule), it says no provider for ShopService.
Is this because ResultService is not declared in appModule, causing the provider in appModule not to work for ResultService? Where would I declare it in AppModule? Because I added it to the declarations of appModule I got:
find:21 Error: (SystemJS) Unexpected value 'ResultService' declared by the module 'AppModule'(…)
code:
ResultService:
import { Injectable } from '@angular/core';
import { Result } from '../result';
import { RESULTS } from '../mock-results';
import { ShopService } from './shop.service';
@Injectable()
export class ResultService {
constructor(private shopService: ShopService) {}
getResults(): Result[] {
RESULTS.forEach(result => {
result.nearbyShops = this.shopService.getShops();
});
return RESULTS;
}
}
ShopService:
import { Shop } from '../result';
import { SHOPS } from '../mock-shops';
import { Injectable } from '@angular/core';
@Injectable()
export class ShopService {
getShops(): Shop[] {
return SHOPS;
}
}
Upvotes: 3
Views: 1006
Reputation: 3548
I had a similar issue -
My "MenuService" depends on a "SecurityService".
I provided both services in the AppModule, but as soon as my MenuService was created, I got the error "No provider for SecurityService".
I know for sure the SecurityService exists because I could log it out on the console.
Note* - Both of these service definitions are imported from external npm packages, because I want to use them in other projects. So this could have an impact on the root cause.
The only solution for me, was to create a MenuServiceFactory to provide the MenuService and pass in the SecurityService to the constructor.
Example test case -
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HeaderComponent } from './header.component';
import { provideRoutes } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { SecurityModule, SecurityService } from '@savantly/ngx-security';
import { MenuModule, MenuService } from '@savantly/ngx-menu';
const menuServiceFactory = (_securityService: SecurityService) => {
return new MenuService(_securityService);
};
describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HeaderComponent ],
imports: [RouterTestingModule, SecurityModule.forRoot(), MenuModule],
providers: [
{
provide: MenuService,
useFactory: menuServiceFactory,
deps: [SecurityService]
},
provideRoutes([])
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
You can also move this factory into the original module if you want consumers to have it easier -
import { NgModule, ModuleWithProviders, SkipSelf, Optional } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MenuComponent } from './menu.component';
import { MenuService } from './menu.service';
import { MdMenuModule, MdToolbarModule, MdButtonModule } from '@angular/material';
import { FlexLayoutModule } from '@angular/flex-layout';
import { SecurityModule, SecurityService } from '@savantly/ngx-security';
@NgModule({
imports: [
CommonModule,
MdMenuModule, MdToolbarModule, MdButtonModule, FlexLayoutModule, SecurityModule
],
exports: [
CommonModule,
MdMenuModule, MdToolbarModule, MdButtonModule, FlexLayoutModule,
SecurityModule,
MenuComponent],
declarations: [MenuComponent],
providers: []
})
export class MenuModule {
static forRoot({securityService = SecurityService}: {securityService?: SecurityService} = {}): ModuleWithProviders {
return {
ngModule: MenuModule,
providers: [{
provide: MenuService,
useFactory: menuServiceFactory,
deps: [securityService]
}]
};
}
constructor (@Optional() @SkipSelf() parentModule: MenuModule) {
if (parentModule) {
throw new Error(
'MenuModule is already loaded. Import it in the AppModule only');
}
}
}
export function menuServiceFactory(_securityService: SecurityService): MenuService {
return new MenuService(_securityService);
}
References -
https://angular.io/guide/dependency-injection#factory-providers
https://github.com/savantly-net/sprout-platform
Upvotes: 0
Reputation: 176
I had similar error with yours
Error: Can't resolve all parameters for services: (?, ?, ?)
and i found a solution with provide my services on NgModule look my answer here
i hope to help you.
Upvotes: 1