Angular 8 resolver is not resolved - javascript

I have console.log in constructor and ngOnInit() of Resolver but which are not logged.
resolve:{serverResolver:ServerResolverDynamicDataService}},
console.log("ServerResolverDynamicDataService constructor");
console.log('ServerResolverDynamicDataService resolve:'
const appRoutes : Routes =[
{path:"",component:HomeComponent},
{path:"servers",canActivateChild:[AuthGuardService],component:ServersComponent,
children:[
{path:":id",component:ServerComponent,
resolve:{serverResolver:ServerResolverDynamicDataService}},
{path:":id/edit",component:EditServerComponent,canDeactivate:[CanDeativateGuardService]}]},
Resolver:
#Injectable()
export class ServerResolverDynamicDataService implements Resolve<ServerModel>{
constructor(private serversService:ServersService){
console.log("ServerResolverDynamicDataService constructor");
}
resolve(activatedRouteSnapshot: ActivatedRouteSnapshot, routerStateSnapshot:
RouterStateSnapshot): ServerModel | Observable<ServerModel> | Promise<ServerModel> {
console.log('ServerResolverDynamicDataService resolve:'+activatedRouteSnapshot.params['id']);
return this.serversService.getServer(+activatedRouteSnapshot.params['id']);
}
}
Update1: app.module.ts has entry of this service in providers
providers: [ServersService,AuthGuardService,AuthService,CanDeativateGuardService,ServerResolverDynamicDataService],
Whenever URL(http://localhost:4200/servers/1?allowToEdit=0&allowTest=2#loadPage) is getting hit, no logs are coming from resolver but logs are there in code and the application is properly refreshing if I edit any other part of the application log. So app changes are reflecting the only problem is resolver is not called.
Update2
As per Angular 2+ route resolvers not being called if I remove parent canActivateChild service which is working.B ut I don't know what is wrong.Please help me to understand.

A Resolver is a service and OnInit isn't executed in a service. In fact, besides OnDestroy, there's no other lifecycle hook in a service.
Anyway, I'm assuming your resolver is provided somewhere. If it's not, you should use an argument in its decorator: #Injectable({providedIn: 'root'}).

Related

Angular service call a child method in constructor

Is there a way to call a child class method from an abstract service? When I do this, the if statement doesn't execute because onInit doesn't exist. I am not sure why it doesn't exist though. Maybe there is an "angular" way of doing this instead of triggering this on the init. Or maybe I just need to call the onInit manually in the component instead. Basically what I am doing is trying to get the initial application data from the server.
#Injectable({providedIn:'root'})
export class RootService {
public constructor(httpClient: HttpClient) {
if(typeof this.onInit === 'function') {
this.onInit()
}
}
}
#Injectable({providedIn:'root'})
export class MyService extends RootService {
public onInit() {
// Do stuff
}
}
#Component()
export MyComponent {
public constructor(myService: MyService) {}
}
Services do not have lifecycle events. However, components have lifecycle hooks such as:
ngOnChanges()
ngOnInit()
ngDoCheck()
...
So you can load data when your component is initialized. If yes, then just use ngOnInit:
import { Component, OnInit } from '#angular/core';
#Component()
export MyComponent implements OnInit {
yourData;
public constructor(myService: MyService) {}
ngOnInit(){
myService.loadData()
.subscribe(s=> yourData = s);
}
}
According to Angular docs:
OnInit is a lifecycle hook that is called after Angular has
initialized all data-bound properties of a directive.
If you add the service to the providers of your component, it will be in your components scope then you can call onInit in your service as well.
But the downside of this is you can no longer share the same instance of the service among your components.
This will be valid if your service only serves one component.

nestjs exception filter is not invoked

I am trying to use an exception filter in my NestJS app. I followed the instructions found here to setup my global ExceptionFilter, which looks like this:
#Catch()
export class DemoExceptionFilter implements ExceptionFilter
{
private readonly logger: Logger;
constructor()
{
this.logger = new Logger(DemoExceptionFilter .name);
}
public catch(exception: unknown, host: ArgumentsHost): void
{
this.logger.log(exception);
}
}
In my AppModule I have registered the DemoExceptionFilter this way:
#Module({
...
providers: [
...
{
provide: APP_FILTER,
useClass: DemoExceptionFilter
}
...
]
})
When I throw an exception somewhere in my code that exception gets logged by NestJS in the console but my DemoExceptionFilter is not invoked.
I also tried
app.useGlobalFilters(new DemoExceptionFilter());
in main.ts, which also does not work.
What am I missing?
In the documentation, it says where global exception filters will be applied:
Global-scoped filters are used across the whole application, for every controller and every route handler.
They are not used for the application startup. So if you want to test your exception filter, throw an error in the route handler method of a controller and call the route.

Working around with observable and subscriptions

I am using Angular6, below is my scenario:
I am trying to pass information between Component1 and COmponent2 via a service. I see that service receives message from Component1, but Component2 doesnt receive the passed message.
In Page1:
//when a mouse move in a particular area happens, this method is called
actionMove: function(evt,obj) {
var messService = new MessService();
messService.sendMessage('Sending message from Component1 to Component2!');
}
inMessService file:
import { Injectable } from '#angular/core';
import { Observable, Subject } from 'rxjs';
#Injectable({ providedIn: 'root' })
export class MessService {
private subject = new Subject<any>();
sendMessage(message: string) {
console.log("*** service got message from component 1 ***");
this.subject.next({ text: message });
}
getMessage(): Observable<any> { // this communicates with component2
console.log("*** component 2 trying to get message ***");
return this.subject.asObservable();
}
}
In Component2:
constructor(private messService: MessService) {
// subscribe to message service method
this.subscription = this.messService.getMessage()
.subscribe(message => { this.message = message; });
Could you please help me understand what am I missing?
Im not an Angular pro, but I think you using two different instances of MessService here because you new up one in actionMove in component1, and injecting an other one into component2, hence working with one does not reflect in the other.
Try to inject MessService into component1 also using constructor injection, as fridoo suggests. Because you provide your service in root, you'll get a singleton.
Singleton services - Angular
fridoo's comment goes to the heart of it --
to use a service in multiple components you need to take advantage of angular's dependency injection. you want to reference your service class in the constructor like in your component2 in component1, this way both components are using the same MessService.
you can just create an empty constructor like
constructor(private messService: MessService) {}
to get the service injected -- have you tried doing this?

Handling subscribe in service and not component

I have a simple setup in Angular to see how I can retrieve my data from a remote server. The sample project that I made has a component : ServerCompoent
#Component({
selector: 'app-server',
templateUrl: './server.component.html'
})
export class ServerComponent {
constructor(private serverService: ServerService){}
displayServers() {
this.serverService.getServers().subscribe(
(response)=> console.log(response),
(error) => console.log(error)
}
and a service that fetch data from my back-end called: ServerService
#Injectable()
export class ServerService{
constructor (private http: Http) {}
// private instance variable to hold base url
private serverUrl= 'http://localhost:8080/server';
getServer(){
return this.http.get(this.serverUrl);
}
);
}
So for now, everything works like a charm, but is it possible to subscribe to the observable returned in the service and not the component. I think that having .subscribe code part is not really clean. Is there a way to achieve such behavior know that the DI in Angular is Synchronous?
Thank you

Angular 2 Shared Data Service is not working

I have built a shared data service that's designed to hold the users login details which can then be used to display the username on the header, but I cant get it to work.
Here's my (abbreviated) code:
// Shared Service
#Injectable()
export class SharedDataService {
// Observable string source
private dataSource = new Subject<any>();
// Observable string stream
data$ = this.dataSource.asObservable();
// Service message commands
insertData(data: Object) {
this.dataSource.next(data)
}
}
...
// Login component
import { SharedDataService } from 'shared-data.service';
#Component({
providers: [SharedDataService]
})
export class loginComponent {
constructor(private sharedData: SharedDataService) {}
onLoginSubmit() {
// Login stuff
this.authService.login(loginInfo).subscribe(data => {
this.sharedData.insertData({'name':'TEST'});
}
}
}
...
// Header component
import { SharedDataService } from 'shared-data.service';
#Component({
providers: [SharedDataService]
})
export class headerComponent implements OnInit {
greeting: string;
constructor(private sharedData: SharedDataService) {}
ngOnInit() {
this.sharedData.data$.subscribe(data => {
console.log('onInit',data)
this.greeting = data.name
});
}
}
I can add a console log in the service insertData() method which shoes the model being updated, but the OnInit method doesn't reflect the change.
The code I've written is very much inspired by this plunkr which does work, so I am at a loss as to what's wrong.
Before posting here I tried a few other attempts. This one and this one again both work on the demo, but not in my app.
I'm using Angular 2.4.8.
Looking through different tutorials and forum posts all show similar examples of how to get a shared service working, so I guess I am doing something wrong. I'm fairly new to building with Angular 2 coming from an AngularJS background and this is the first thing that has me truly stuck.
Thanks
This seems to be a recurring problem in understanding Angular's dependency injection.
The basic issue is in how you are configuring the providers of your service.
The short version:
Always configure your providers at the NgModule level UNLESS you want a separate instance for a specific component. Only then do you add it to the providers array of the component that you want the separate instance of.
The long version:
Angular's new dependency injection system allows for you to have multiple instances of services if you so which (which is in contrast to AngularJS i.e. Angular 1 which ONLY allowed singletons). If you configure the provider for your service at the NgModule level, you'll get a singleton of your service that is shared by all components/services etc. But, if you configure a component to also have a provider, then that component (and all its subcomponents) will get a different instance of the service that they can all share. This option allows for some powerful options if you so require.
That's the basic model. It, is of course, not quite so simple, but that basic rule of configuring your providers at the NgModule level by default unless you explicitly want a different instance for a specific component will carry you far.
And when you want to dive deeper, check out the official Angular docs
Also note that lazy loading complicates this basic rule as well, so again, check the docs.
EDIT:
So for your specific situation,
#Component({
providers: [SharedDataService] <--- remove this line from both of your components, and add that line to your NgModule configuration instead
})
Add it in #NgModule.providers array of your AppModule:
if you add it in #Component.providers array then you are limiting the scope of SharedDataService instance to that component and its children.
in other words each component has its own injector which means that headerComponentwill make its own instance of SharedDataServiceand loginComponent will make its own instance.
My case is that I forget to configure my imports to add HttpClientModule in #NgModules, it works.

Categories