How to declare a service with Angular5 - javascript

I have an Angular service that looks like this
#Component({})
#Inject(ChromeDataService)
#Injectable()
export class MainDataService {
}
when I run ng build --prod, I get this error
ERROR in : No template specified for component MainDataService
my only guess is that an Angular service does not need to be a component? So I removed the #Component annotation, but then I get this:
ERROR in : Unexpected value 'MainDataService in
/home/.../main.ts'
declared by the module 'SharedModule in
/home/.../src/app/shared.module.ts'.
Please add a #Pipe/#Directive/#Component annotation.
Uh, how do I create a service in Angular5?

To use an angular service properly you only need injectable()
Here's an example
#Injectable()
export class myService {
//some logic
}
then in your app.module or in a feature module you add the service in the providers array and to have the angular DI handle the service for you.
#Component({
usual stuff with template, selector, css})
export class someComponent {
constructor(private myService: MyService){}
}
The constructor will tell angular to auto-magically inject the service you need in.

your service only needs the #Injectable() decorator.like this
import {Injectable} from '#angular/core'
import {Router} from '#angular/router'
#Injectable()
export class AuthService {
constructor(private router: Router) {}
}

That's how I declare services in Angular:
#Injectable()
export class AuthService {
...
}
I think you only need #Injectable decorator. Maybe your problem comes from shared.module.ts.

Related

Inject nestjs service from another module

I've got a PlayersModule and an ItemsModule.
I want to use the ItemsService in the PlayersService.
When I add it by injection:
import { Injectable } from '#nestjs/common';
import { InjectModel } from 'nestjs-typegoose';
import { ModelType, Ref } from 'typegoose';
import { Player } from './player.model';
import { Item } from '../items/item.model';
import { ItemsService } from '../items/items.service';
#Injectable()
export class PlayersService {
constructor(
#InjectModel(Player) private readonly playerModel: ModelType<Player>,
private readonly itemsService: ItemsService){}
I get this nest error :
[Nest] 11592 - 2018-8-13 11:42:17 [ExceptionHandler] Nest can't
resolve dependencies of the PlayersService (+, ?). Please make sure
that the argument at index [1] is available in the current context.
Both modules are imported in the app.module.ts. Both services are working alone in their module.
You have to export the ItemsService in the module that provides it:
#Module({
controllers: [ItemsController],
providers: [ItemsService],
exports: [ItemsService]
^^^^^^^^^^^^^^^^^^^^^^^
})
export class ItemsModule {}
and then import the exporting module in the module that uses the service:
#Module({
controllers: [PlayersController],
providers: [PlayersService],
imports: [ItemsModule]
^^^^^^^^^^^^^^^^^^^^^^
})
export class PlayersModule {}
⚠️ Don't add the same provider to multiple modules. Export the provider, import the module. ⚠️
Let' say you want to use AuthService from AuthModule in my TaskModule's controller
for that, you need to export authService from AuthModule
#Module({
imports: [
....
],
providers: [AuthService],
controllers: [AuthController],
exports:[AuthService]
})
export class AuthModule {}
then in TaskModule, you need to import AuthModule (note: import AuthModule not the AuthService in TaskModule)
#Module({
imports:[
AuthModule
],
controllers: [TasksController],
providers: [TasksService]
})
export class TasksModule {}
Now you should be able to use DI in TaskController
#Controller('tasks')
export class TasksController {
constructor(private authService: AuthService) {}
...
}
The question is answered by Kim Kern. But I just want to remind people who read through this comment. Whenever you get this error, you should follow these steps that may help you easily figure out where the stuck is:
Make sure the Module which provides providers was imported.
Make sure the provider which you are using is exported.
For example, you have category module which contains category service, post module has post service and it has category service as a dependency:
#Module({
controllers: [CategoryController],
providers: [CategoryService],
exports: [CategoryService] // Remember to export
})
export class CategoryModule {}
And
#Module({
imports: [CategoryModule], // Make sure you imported the module you are using
controllers: [PostController],
providers: [PostService]
})
export class PostModule {}
Don't forget to use this annotation.
Nest uses this to detect singleton class.
In spring boot - Java, this one used to be called Bean. Read more:
#Injectable()
export class PostService {
constructor(private readonly categoryService: CategoryService // This will be auto injected by Nestjs Injector) {}
}
I solved my problem by removing #Inject() from the argument in my constructor that was passing the exported service.
I believe that you faced the same problem i had. My scenario was 2 sibling custom modules (user, auth) that needed to use each other's services. I used circular DI to solve it. please check this link
Let me know whether if it solved your issue, maybe I can advise you further.
Solved my problem by changing the way of importing the constant string (TOKEN) used in #Inject()) of my provider... be careful using index.ts whith export * from module.ts, nest won't resolve the dependecy
Based on the answer by Kim Kern nowadays we should add only injected service into our service without any decorators (#Inject() doesn't required). After that it will work right. That was my mistake and probably can help others.
Steps 1. Export the file that you want
Step 2. Import the whole module.
I initially made a mistake of adding the file as provider and also adding the module which was throwing error.

No provider for service error in angular2, why do I need to inject it in it's parent component?

I have a pages.service.ts
import { Injectable } from '#angular/core';
import { ApiService } from '../../apiService/api.service';
import { Playlists } from '../shared/playlists.model';
#Injectable()
export class PagesService {
private currentPlaylists: Subject<Playlists> = new BehaviorSubject<Playlists>(new Playlists());
constructor(private service: ApiService) {
}
}
This pages service needs another service called ApiService, I inject the way as shown above, it works.
I bootstrap ApiService in main.ts
import { ApiService } from './apiService/api.service';
import { AppComponent } from './app.component';
bootstrap(AppComponent,[
disableDeprecatedForms(),
provideForms(),
HTTP_PROVIDERS,
ROUTER_PROVIDERS,
ApiService
]).catch((err: any) => console.error(err));;
But When I try to inject the PagesService to another component, it gives me error, No Provider for PagesService.
I write that component like this.
import { Component, ViewChild, ElementRef, Input, Output, EventEmitter } from '#angular/core';
import { CORE_DIRECTIVES } from '#angular/common';
import { MODAL_DIRECTVES, BS_VIEW_PROVIDERS } from 'ng2-bootstrap/ng2-bootstrap';
import { ApiService } from '../../apiService/api.service';
import { PagesService } from '../../pages/shared/pages.service';
#Component({
selector: 'assign-playlist-modal',
exportAs: 'assignModal',
providers: [ PagesService ],
directives: [MODAL_DIRECTVES, CORE_DIRECTIVES, FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES ],
viewProviders: [BS_VIEW_PROVIDERS],
styleUrls: ['app/channel/shared/assignPlaylist.css'],
templateUrl: 'app/channel/modals/assignPlaylistModal.html'
})
export class AssignPlaylistModalComponent {
constructor(private apiService: ApiService, private pageService: PagesService, fb: FormBuilder) {
}
}
Update: this is my file structure
channel/
--channel.component.ts
--shared/
----assignPlaylist.modal.ts
----addPlaylist.modal.ts
pages/
--shared/
----pages.service.ts
--pages.component.ts
Channel component is the parent of addPlaylist, addPlaylist is the parent of assignPlaylist. This structure will not work
ChannelComponent
|
AddPlaylistComponent
|
AssignPlaylistComponent ----PagesService----ApiService
I found one solution but don't know why I need to do that,
I add the provider 'PagesService' to ChannelComponent, and also the AssignPlaylistComponent, it will work, no errors.
Even this will work
ChannelComponent ----PagesService-------------
|
AddPlaylistComponent
|
AssignPlaylistComponent ----ApiService---------------
However, I just want to use PagesService in AssignPlaylistComponent, so I think it not make sense to import PagesService in channelcomponent.ts and make a providers array in it.
It is a bit strange, but only components can configure dependency injection in Angular (well, and bootstrap()). I.e., only components can specify providers.
Each component in the component tree will get an associated "injector" if the component has a providers array specified. We can think of this like an injector tree, that is (normally much) sparser than the component tree. When a dependency needs to be resolved (by a component OR a service), this injector tree is consulted. The first injector that can satisfy the dependency does so. The injector tree is walked up, toward the root component/injector.
So, in order for your PagesService to inject a ApiService dependency, that ApiService object first has to be registered with an injector. I.e., in a component's providers array. This registration must occur somewhere at or above the component where you want to use/inject the ApiService .
Your service should then be able to inject the registered ApiService object, because it will find it in the injector tree.
See also Angular 2 - Including a provider in a service.

How can I add providers to a Service class in Angular 2?

I have a component that uses a service. The component looks something like this:
#Component({
moduleId: module.id,
selector: 'test',
providers: [HTTP_PROVIDERS, TestService]
})
export class TestComponent implements OnInit {
constructor(private _testService:TestService) {
}
As you can see, I added the HTTP_PROVIDERS provider in my component. This worked since the DI is now aware of the http classes. However, it was my TestService that was really using the Http class, not my TestComponent.
#Injectable()
export class TestService {
constructor(private _http:Http) {
}
I felt that since it is the service using the Http class, it should be the one including the providers in itself. The TestComponent wouldn't know what providers TestService would need.
Since the service class doesn't have that component decorator, I'm not sure how I can actually add providers to it. How can I add providers to a Service class?
What you can do is,
Inject HTTP_PROVIDERS into bootstrap function ,
import {HTTP_PROVIDERS} from '#angular/http';
bootstrap(AppComponent,[HTTP_PROVIDERS]);
and in your service,
import {Http} from '#angular/http';
#Injectable()
export class TestService {
constructor(private _http:Http) {}
}

Angular2: Service with Model - "no provider for model"

What I'm trying to do is create a service that uses a model to show an alert. The alert-model should be necessary nowhere else but in that service but I am not able to make this work. My service:
import {Injectable, Inject} from "angular2/core";
import {AlertModel} from "../models/alert.model";
#Injectable()
export class AlertService {
constructor(#Inject(AlertModel) alertModel: AlertModel) {
}
public alert(){
this.alertModel.message = 'success';
//...
}
}
But I keep getting this error:
Uncaught (in promise): No provider for AlertModel! (UserComponent -> AlertService -> AlertModel)
I'm new to angular and I do not understand this. What am I missing? Thanks in advance!
You need to provide the AlertModel somewhere
bootstrap(AppComponent, [AlertModel])
or in the root component (preferred):
#Component({
selector: 'my-app',
providers: [AlertModel],
...
})
Ensure AlertModel has the #Injectable() decorator and all its constructor parameters are provided as well (if it has any)
#Inject(AlertModel) is redundant if the type of the constructor parameter is already AlertModel. #Inject() is only necessary if the type differs or if AlertModel doesn't have the #Injectable() decorator.
constructor(#Inject(AlertModel) alertModel: AlertModel) {
You have this error since there is no provider for the AlertModel class visible from the UserComponent component (that calls the service). You can define either this class in the providers attribute of the component either when bootstrapping your application.
See the question to know more about how hierarchical injectors works and how to inject things into services:
What's the best way to inject one service into another in angular 2 (Beta)?
Since the AlertModel class seems to be a model class I don't think that you need to inject it. You can simply import the class and instantiate it:
#Injectable()
export class AlertService {
alertModel: AlertModel = new AlertModel();
public alert(){
this.alertModel.message = 'success';
//...
}
}

Inserting multiple services into a service - angular2

I am trying to inject a self created service & the angular2 Http service into my custom HttpRest service.
using
#Inject(Http) public _http: Http
worked fine, but when I try to inject another self made service i get following Error:
EXCEPTION: Cannot resolve all parameters for 'HttpRest'(Http #Inject(Http), undefined #Inject(undefined)). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'HttpRest' is decorated with Injectable.
For some reason
UserIds is undefined, even though the import is succesful.
My custom service:
#Injectable()
export class UserIds{
private _signature_id:string;
private _role_id:number;
get signature_id():string{
return this._signature_id;
}
set signature_id(id:string){
this._signature_id = id;
}
get role_id():number{
return this._role_id;
}
set role_id(id:number){
this._role_id = id;
}
}
The Custom HttpRest service im injecting both Http & UserIds into:
#Injectable()
export class HttpRest{
groups;
constructor(
#Inject(Http) public _http: Http,
#Inject(UserIds) public _ids: UserIds
){}
...
}
NOTE! when I remove
,
#Inject(UserIds) public _ids: UserIds
I dont get the Error.
What am I missing ?
UPDATE
The problem is actually that UserIds is undefined in the constructor params for some unknown reason that im trying to understand, so the title of this question becomes irrelevant. It should be "Imported service is undefined in constructors params".
Please reffer to my answer on this question further down this post.
UPDATE:
Please reffer to a question that discusses this issue.
Using index.ts file to export class causes undefined in injected constructor
#Inject(...) in #Inject(Http) public _http: Http is redundant when the parameter to #Inject() is the same as the type of the parameter.
#Injectable()
export class HttpRest{
groups;
constructor(public _http: Http, public _ids: UserIds
){}
...
}
You need to provide Http and UserIds so DI is able to resolve the dependency. Http is included in HTTP_PROVIDERS
#Component({
selector: '...',
providers: [HTTP_PROVIDERS, UserIds],
template: ...
})
export class AppComponent {
}
Ensure you have everything imported correctly
import {HTTP_PROVIDERS, Http} from 'angular2/http';
Ok so I found the problem, and it has not to do with Inject.
The problem was that im using an index file to export services, as mentioned in the angular 2 style guide (https://github.com/mgechev/angular2-style-guide/blob/master/old/README.md#directory-structure), and for some reason importing this specific service from the index causes an undefined value when injected into the constructor.
When I reffernced the source directly and not trough the index file, for some reason that is unknown to, resolved the Error.
The import before the fix looked like this:
import {UserIds} from "../index";
Which worked with all other services and components.
The import using the direct source file:
import {UserIds} from "../user_ids/user_ids.service";
For some reason this solved my problem, but i want to stay consistent with the index.ts encapsulation.
If anyone has an idea why this could happen I'll be happy for updates.
You need to register your UserIds service at the root level (main.ts) or in the app.component.ts, which is the highest level in the hierarchy:
#Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>',
providers: [ UserIds ]
})
export class AppComponent { }

Categories

Resources