It is possible generate a service with angular cli and add it as a provider in the app.module.ts in a single step or using an special option in the ng g service command?
When a execute:
$ ng g service services/backendApi
installing service
create src/app/services/backend-api.service.spec.ts
create src/app/services/backend-api.service.ts
WARNING Service is generated but not provided, it must be provided to be used
Next to it, (and according to the WARNING message) I usually add it to provider section on app.module.ts using the text editor:
#NgModule({
declarations: [
AppComponent,
...
],
imports: [
....
],
providers: [BackendApiService],
bootstrap: [AppComponent]
})
It is possible to do it with a single step, to automatize this?
Actually, it is possible to provide the service (or guard, since that also needs to be provided) when creating the service.
The command is the following...
ng g s services/backendApi --module=app.module
Edit
It is possible to provide to a feature module, as well, you must give it the path to the module you would like.
ng g s services/backendApi --module=services/services.module
Angular 6+ Singleton Services
The recommended approach for a singleton service for Angular 6 and beyond is :
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root',
})
export class UserService {
}
In fact the CLI --module switch doesn't even exist any more for registering a service at the app level because it doesn't need to modify app.module.ts anymore.
This will create the above code, without needing to specify a module.
ng g s services/user
So if you don't want your service to be a singleton you must remove the providedIn code yourself - and then add it manually to providers for a component or lazy loaded module. Doesn't look like there is currently a switch to not generate the providedIn: 'root' part so you need to manually remove it.
Looks like in Angular v11 and higher, we don't have option "s" anymore:
ng g service services/backendApi
or like that:
ng g service services/backendApi --flat --skipTests=true
Specify paths
--app
--one
one.module.ts
--services
--two
two.module.ts
--services
Create Service with new folder in module ONE
ng g service one/services/myNewServiceFolderName/serviceOne --module one/one
--one
one.module.ts // service imported and added to providers.
--services
--myNewServiceFolderName
serviceOne.service.ts
serviceOne.service.spec.ts
slight change in syntax from the accepted answer for Angular 5 and angular-cli 1.7.0
ng g service backendApi --module=app.module
Add a service to the Angular 4 app using Angular CLI
An Angular 2 service is simply a javascript function along with it's associated properties and methods, that can be included (via dependency injection) into Angular 2 components.
To add a new Angular 4 service to the app, use the command ng g service serviceName. On creation of the service, the Angular CLI shows an error:
To solve this, we need to provide the service reference to the src\app\app.module.ts inside providers input of #NgModule method.
Initially, the default code in the service is:
import { Injectable } from '#angular/core';
#Injectable()
export class ServiceNameService {
constructor() { }
}
A service has to have a few public methods.
In Angular 5.12 and latest Angular CLI, do
ng generate service my-service -m app.module
ng generate service userService
//shorthand for creating service
ng g s serviceName
**
When you fire this command it will automatically registered inside providers array.
**
providers: [
UserService
]
In Command prompt go to project folder and execute following:
ng g s servicename
run the below code in Terminal
makesure You are inside your project folder in terminal
ng g s servicename --module=app.module
Related
I have an angular application with defined services. and I also have a couple of libraries defined. what I can't do is use an application service within one of my libraries.
src
app
service
myappservice.service.ts
project
mylib
src
lib
mylibservice.service.ts
when I try to import "myappservice" into "mylibservice" it gives me this error:
... is not under 'rootDir' .... 'rootDir' is expected to contain all source files.
mylibservice.service.ts
import { MyAppService} from 'src/app/services/myappservice.service';
#Injectable({
providedIn: "root",
})
export class ObjectTypesService {
...
constructor(
private myappservice: MyAppService
) {
...
Can someone help me with to use this service within my library?
You can build your lib module, publish it to npm and add it in package.json via npm.
You can build your lib module and instead of publishing it to npm you can import .tgz file in package.json.
You can use some monorepo that already solve this problem like https://nx.dev/ . In this solution you store all libs and app in same git repo and you can import libs to apps without publishing it to npm after every change. This has dowside because you must build every time app and all libs.
Is posible build lib in this monorepo as npm package too. If you need use it in other app that is outside monorepo or in app from monorepo as npm dependency.
i have made a UI Library in Angular 8 and am using this library into my another custom library, But when am importing my modules from parent library it throws this error Unexpected value 'DefaultButtonModule Please add a #NgModule annotation .
angular cli : 8.3.0
node: 10.15.0
am using these versions.
I have tried white listing non peer dependencies and exporting modules.
Am using Angular material in my parent library.
You need to export and import the files explicitly.
If it's a module file it is to imported from the .module file i.e,
import {Module} from './path/file.module'
If you keep all exports in the index.ts file make sure you also specify /index in the path when you're importing i.e,
export * from './path/index
I use nrwl.io in my project.
I created several libs:
ng g lib rest //ok
ng g lib services //ok
ng g lib models //created ok, but "Cannot find module " later on!
All of these libs were successfully created, but when I try to import my models lib I see error "Cannot find module":
import { ModelA, ModelB } from '#myproj/models'; //Cannot find module '#myproj/models'
The question is: How and where I can check if my '#myproj/models' was properly registered?
P.S. I can see "models" module in nx.json, angular.json and tsconfig.json. And I can see no difference with other modules.
P.P.S. I use "#nrwl/nx": "6.1.0" and "#nrwl/schematics": "6.1.0"
In my case it was because I was dumb and didn't restart my TypeScript server in VS Code:
CMD / CTRL + SHIFT + P
>TypeScript: Restart TS Server
I also had the same issue. Created a library and tried to use it in multiple projects.
First make sure your library is added in main tsconfig.json -> paths property.
"paths": {
"#projectName/LibraryName1": ["libs/LibraryName1/src/index.ts"],
"#projectName/LibraryName2": ["libs/LibraryName2/src/index.ts"],
....
}
Then you must have your project added in your main angular.json file.
"projects": {
"LibraryName1": {
"root": "libs/LibraryName1",
"sourceRoot": "libs/LibraryName1/src",
"projectType": "library",
"prefix": "projectName",
"projectType": "library"
...
}
}
Then obviously check tsconfig.json file for that app in which you are going to use lib. The key is to remove paths property. Because you already added in main tsconfig.json (in my case I used nrwl (a technique for managing multiple apps)).
Now you should be able to reference any of your lib projects like so :
import { class1,class2 } from '#projectName/libraryName1';
Don't forget to export your classes (assuming you have models library ) using index.ts like so :
export * from './lib/class1';
export * from './lib/class2';
Or
If you have any UI library that have components. You should create a module add those components in it and then export it using index.ts
The module file should be in lib folder. e.g
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { NumberOnlyDirective } from './directives/number-only.directive';
#NgModule({
imports: [CommonModule],
declarations: [NumberOnlyDirective],
exports: [NumberOnlyDirective]
})
export class UiModule {}
index.ts file for UI library
export * from './lib/ui.module';
Add UI module's reference in your project app.module.ts
import { UiModule } from '#projectName/LibraryName1';
in imports also
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
NgxPaginationModule,
Ng2OrderModule,
Ng2SearchPipeModule,
AngularEditorModule,
RichTextEditorAllModule,
NgxPrintModule,
DevExpressModule,
UiModule
...
],
I also encountered this issue.
Assume the project is named "project1" and the library is named "libray1" (so we're trying to reference the module "#project1/library1"). Referencing the NRWL NX generated library modules works fine from non-Angular (in my particular case Ionic/Angular) contexts, but caused the "Cannot find module" error from Angular apps within the monorepo.
The problem occurred because the Angular application was looking for the barrel file (index.ts) in the location "project1/libs/library1", whereas NX puts the barrel one level down in "project1/libs/library1/src".
The (slightly annoying) solution is to create an additional index.ts file at the "project1/libs/library1" location with the following content:
export * from './src';
This ensures that the code works from all contexts, and is a fix-once solution (for each new library you generate) as opposed to having to add an explcit reference to the package.json file of each Angular app in the repo.
In case anyone is experiencing this and mentioned solutions didn't help, here's how I fixed it.
After a while I realized that I could import fine in other places, only the app I was trying had the issue
This lead me to check tsconfig of the app
I found that I had set baseUrl: true in tsconfig, which was the reason why the import couldn't be resolved.
TLDR: Remove baseUrl setting from tsconfig.
This is the answer for anyone who integrated nx to an existing monorepo and got this error.
You need to add root tsconfig.base.json to your application tsconfig.json using something like
{
...
"extends": "../../tsconfig.base.json",
....
}
I had the same issue when I was trying to create new lib. I removed the node_modules and reinstall it back. It fixed the issue
While you import something using #model/something, editor will automatically add a full path to the module (in my case). so this is what I had to do to get the import '#' working.
delete the editor added full path import. keep only the one you are typing- ie; with #project/models.
turn the server off and ng serve again.
This is where using --parent-module=apps/myapp/src/app/app.module.ts comes in when creating a lib.
One of the things that flag does is modify the tsconfig.app.json and adds "../../libs/mylib/src/index.ts to the includes which tells TS to use the module.
I am working to an Angular 2 application which has only one module with several services registered as providers at bootstrap. The application has also several components in the same module which are using these services.
All components are receiving the services using DI (services are declared as parameters in construtor).
The problem that I am facing is: the same service is correctly injected in some components but in other no.
I checked the Injector object for the components where the injection fails and the services instances are within the Injector object. What it fails is the searching with the Injector.get() method. The token provided as parameter is different from the token stored in the Injector dictionary. I am not able to find out why because I am using the class name of the service and the token is automatically generated by the Javascript engine from this class name.
I tried to use OpaqueTokens to control the injection and, again, even if I am using the same opaque token, when Injector.get() method is called, the token provided by argument is considered different from the token stored by injector.
A short fragment from the code looks like
myservice.service.ts
import { OpaqueToken } from '#angular/core'
export const BACKEND = new OpaqueToken('backend');
app.module.ts
import { BACKEND } from 'myservice.service'
...
providers: [{ provide: BACKEND, useValue: "TestValue" }]
mycomponent.component.ts
import { Component, Inject } from '#angular/core'
import { BACKEND } from 'myservice.service'
#Component(
{
selector:'mycomponent'
templateUrl: ...
})
export class MyComponent
{
constructor(#Inject(BACKEND) config: string) {
console.info(JSON.stringify(config));
}
}
This injection with BACKEND token works for some components but for other not (the empty {} object is injected). I tried to debug the Javascript code in browser and it looks like the Injector is called with a different token than the token from dictionary (they are looking the same, with the same name 'backend' but still different and === returns false).
Note: I am using Angular 2.4.2, Typescript 2.1 with 'commonjs' modules and 'node' module resolution. systemjs is used as module loader.
Please, can you provide some ideeas about how to fix this?
Thanks,
Do you have various declarations of providers from different modules/components? For every declaration inside the providers array, angular will create a new instance of these services.
Do you have included the parentheses in the #Injectable decorator? https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#injectable
NGmodule gives a way to organise our code in modules.
It also proposes to provides some services as a property of the module and I dont understand the way it works.
First does it mean that if I add a service in the provides property of a NGmodule, it will expose the service (meaning that I have to call the module inside of another one to use its services ) ?
And so, is there a NGmodule injector level ?
How Can I use a service outside the module box in another module ?
Providing a service in a modules means that the service will be instantiated and made available to all components, directives, and pipes that are part of the module. The word 'instantiation' is key here - since services are singletons, a module must keep track of services for every components, directive, or pipe that uses them. You could also provide the service in individual components, but that would instantiate the service each in each component, effectively negating the reason why we would use a singleton service in the first place. Providing it at the module-level solves this problem for us.
If you want to make your service available outside of your module, then don't have to do anything. Providing the service within a module that is imported in your project means that it's already available anywhere in your project.
Related: Why is a service provided in a feature module available everywhere?
If you wanted to make components, directives, or pipes available outside of your module, then you have to export them (and import them in the module where you want to use them). You can do that by using the export keyword in your module.
Related: What classes should I export?
For example, you can use the NgIf directive because it's exported from the CommonModule (docs), which we then import in our own modules:
#NgModule({
declarations: [COMMON_DIRECTIVES, COMMON_PIPES],
exports: [COMMON_DIRECTIVES, COMMON_PIPES],
providers: [
{provide: NgLocalization, useClass: NgLocaleLocalization},
],
})
Fun fact: if you only have one module (the root module that's bootstrapped), then you would actually only use the BrowserModule instead of the CommonModule. The reason all of the functionality of CommonModule is in BrowserModule is because BrowserModule just imports and the re-exports the entire CommonModule.
There's a great in-depth guide to the module system on angular2's website if you want more info. The FAQ page that I linked before is also super useful.