Angular Pass HttpClient from app.module to another module to a service - javascript

I am developing an Angular (ngx-*) NPM Package. I have it compiled properly, and am using it in a new fresh project using npm link
The service has the following constructor to inject HttpClient and settings.
Updated.
MyService
constructor(private http: HttpClient, #Inject('configs') configs: ImyConfigs) {
MyService.Module
I have the following for root in the module
#NgModule({
declarations: [
],
imports: [
CommonModule,
// note that I am not importing HttpClientModule
// My understanding is that if I do I will get duplicate issues?
],
exports: [],
providers: []
})
export class MyModule {
static forRoot(configs?: ImyConfigs): ModuleWithProviders {
return {
ngModule: MyModule,
providers: [MyService, { provide: 'configs', useValue: configs }]
};
}
App.module
Now in my main project (fresh Angular project using this module) I want to use this service.
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule,
MyModule.forRoot(MYCONFIG_CONST)
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
I keep getting the following error:
ERROR Error: StaticInjectorError(AppModule)[MyService -> HttpClient]:
StaticInjectorError(Platform: core)[MyService -> HttpClient]:
NullInjectorError: No provider for HttpClient!
What am I doing wrong with regards to injecting the HttpClient into myService?
Edit: I will answer below.

ng serve --preserve-symlinks
Solved the problem.
This is an old project and it was already added to package.json, I just forgot about it ― for ... to long.

Related

How to use component from module in entryComponents another module?

I have ngx-bootstrap modal component. This modal is used inside shared folder. I use this FirstModalComponent in my DashboardModule like:
// Dashboard.module.ts
import { FirstModalComponent } from '../../shared/modals/first-modal/first-modal.component';
#NgModule({
declarations: [
DashboardComponent
],
imports: [
CommonModule,
ReactiveFormsModule,
RouterModule.forChild(routes),
SharedModule
],
entryComponents: [
FirstModalComponent
]
});
And if I want to make my FirstModalComponent as module, how I should implement it in my DashboardModule and define it in entryComponents?
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { FirstModalModule } from './first-modal/first-modal.module';
#NgModule({
declarations: [],
imports: [
CommonModule,
FirstModalModule
],
exports: [
CommonModule,
FirstModalModule
]
})
export class ModalsModule { }
Then I import/export this ModalsModule in SharedModule and trying to import shared module into DashboardModule.
How can I inject my FirstModalComponent to entryComponents in Dashboard now?
I get an error when I try to import FirstModalComponent and put to entryComponents: Component is part of the declaration of 2 modules.
P.S. I'm not sure that this is a good idea to make it as module..
You should be declaring the FirstModalComponent in only one module. It can be part of one module and exported by the same and can be defined as entryComponent for it's own module.
For your case, declare it as
entryComponents: [
FirstModalComponent
]
for the FirstModalModule and export the FirstModalComponent from FirstModalModule. It will work as expected when you import FirstModalModule inside ModalsModule or any other module in your application.
Make sure this FirstModalModule is exported by your ModalsModule and the SharedModule depending on your use. if you want to use it by importing SharedModule into your DashboardModule, this has to be exported from SharedModule.

Issue setting up dependencies for Angular testbed with ng bootstrap elements despite importing NgbModule.forRoot()

I'm having trouble setting up the dependencies for a component that includes an ng bootstrap modal. The following code is from a test project that isolates the issue. The component works and runs with no errors when the website is served but there seems to be a dependency issue with the tests. I'm using the NgbModal service to open and close the modal within the component. Here's the setup of the component:
#Component({
selector: 'app-main-component',
templateUrl: './main.component.html',
styleUrls: ['./main.component.css'],
providers: [ NgbModal ]
})
export class MainComponent implements OnInit {
constructor(private modalService: NgbModal) { }
and here's where the dependencies are set up in the app.module.ts:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { MainComponent } from './main/main.component';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
#NgModule({
declarations: [
AppComponent,
MainComponent
],
imports: [
BrowserModule,
NgbModule.forRoot()
],
bootstrap: [AppComponent]
})
and the dependencies for the testbed are set up in the main.component.ts file here:
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MainComponent ],
imports: [ NgbModule.forRoot(), BrowserModule ],
providers:[ NgbModal ]
})
.compileComponents();
component = TestBed.get(MainComponent);
modalService = TestBed.get(NgbModal);
}));
When I try to run the tests it's giving me this error
Failed: StaticInjectorError(DynamicTestModule)[NgbModal -> NgbModalStack]:
StaticInjectorError(Platform: core)[NgbModal -> NgbModalStack]:
NullInjectorError: No provider for NgbModalStack!
which seems to imply there's a missing dependency. With errors like this in the main app it seems like it's usually caused by the NgbModule.forRoot() not getting imported but it's in the imports for the test.
Thank you for your time.
Turns out the issue wasn't in my main component spec file, it was an issue running the test for my app component spec file. Since the component was used in the main app component it needed to have the same imports in the app component spec file.

creating an angular package that has RouterModule as a dependancy

I'm trying to create a package using
Angular library starter
Everything works fine until I add RouterModule.
The module that causes an issue
import { NgModule, ModuleWithProviders } from '#angular/core';
import { CommonModule } from '#angular/common';
import { ClientMenuComponent } from './client-menu/client-menu.component';
import { ClientMenuItemComponent } from './client-menu-item/client-menu-item.component';
import { RouterModule, Router, Routes } from '#angular/router';
#NgModule({
imports: [
CommonModule,
RouterModule.forRoot([]) <---- Error: AoT compilation failed
],
declarations: [
ClientMenuComponent,
ClientMenuItemComponent,
],
exports: [
ClientMenuComponent,
ClientMenuItemComponent
]
})
export class ClientMenuModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: ClientMenuModule,
providers: []
};
}
static forChild(): ModuleWithProviders {
return {
ngModule: ClientMenuModule,
providers: []
};
}
}
This is the full error I get.
Error during template compile of 'ClientMenuModule'
Function calls are not supported in decorators but 'RouterModule' was called.
Error: AoT compilation failed
The environment that i'm using is
Angular CLI: 6.0.3
Node: 8.11.1
OS: darwin x64
Angular: 6.0.0
Pull out the function call:
export const MyModule = RouterModule.forRoot([]);
#NgModule({
imports: [
CommonModule,
MyModule
],
declarations: [
ClientMenuComponent,
ClientMenuItemComponent,
],
exports: [
ClientMenuComponent,
ClientMenuItemComponent
]
})
If this is a library or a module that will be imported into other libraries/modules you SHOULD NOT call the .forRoot() function when you pass it into the #NgModule.
RouterModule declares and exports some directives, e.g. router-outlet, routerLink, routerLinkActive etc. Also, it provides some services e.g. Router, ActivatedRoute etc. To avoid having multiple instances of services, RouterModule defines two methods, "forRoot" and "forChild". As the name suggests, "forRoot" method should be called only by root module, i.e. app.module, and forChild should be called by other feature modules. This way, you still get to use directives, components, pipes exported by this module and don't get new instances of services.
While this doesn't specifically get the root of your issue, it will likely resolve your issue. (Also this issue may help)

Angular 2 shared module circular dependency

I have a share module that looks like this:
#NgModule({
exports: [
CommonModule,
HttpModule,
OneModule,
TwoModule
]
})
export class SharedModule {
}
The OneModule imports the SharedModule because he needs access to the other shared modules.
#NgModule({
imports: [SharedModule],
declarations: [SomeComponent]
})
export class OneModule {
}
When I console log the SharedModule I get undefined because I have circular dependency. How can I solve this?
Your SharedModule imports OneModule which imports SharedModule which imports OneModule and so on.
To avoid this, you should try to make SharedModule have a SharedService that you can include in all your components, try to regroup the 'logical thinking' of your code in services.

Angular 2 lazy loaded module - service not singleton

I have implemented lazy loading modules into my application, the app.module.ts is configured correctly.
#NgModule({
declarations: [
AppComponent,
HeaderComponent,
HomeComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
routing
],
bootstrap: [AppComponent]
})
export class AppModule { }
The routing configuration
const APP_ROUTES: Routes = [
{ path: '', component: HomeComponent },
{ path: 'tools', loadChildren: 'app/tools/tools.module#ToolsModule' }
];
export const routing = RouterModule.forRoot(APP_ROUTES);
Providing a service through the providers field in the child module and switching between components of that module reinstantiates that service (tested by logging in the service constructor).
The service is provided in the module only.
#NgModule({
declarations: [
ToolsComponent,
ToolsCartComponent,
ToolsContainerComponent,
ToolsFormComponent
],
imports: [
CommonModule,
toolsRouting
],
providers: [ToolsService]
})
export class ToolsModule { }
Why isn't the provided service not a singleton?
EDIT:
I have modified a plunker example for lazy loading modules by adding a service scoped only to that module (backend module in this case). Switching between BackendComponent and BackendSecondComponent (which are both declared under the lazy loaded module) the service gets reinstantiated (visible in the console)
Plunker link
I believe this is a known issue, tracked here https://github.com/angular/angular/issues/12869.
I think this is the same problem as this Stackoverflow post: How do I provide a service in a lazy-loaded module and have that service scoped to just the lazy-loaded module and its components?
The solution was to create a "root component" in the lazy loaded module and add the components to this new root component.

Categories

Resources