Reputation: 493
I'm converting from AngularJS to Angular6 currently but am not finding any solutions to this question.
Where is it best practice to keep app logic that needs to run on every page that the angular app loads on?
Example logic is logging a user in based on a cookie stored on the machine. Where should I put this logic to check for the cookie and log the user in?
The best place I've seen thus far is in app.component.ts
. I used to accomplish this in AngularJS via loading a GlobalController
on all pages and then loading a HomepageController
etc that would load for the specific "partial" that was plugged into the page.
e/ To clarify, this was just an example and isn't the ONLY business logic I need to run on every page. I need to trigger backend requests every ~10 seconds that check timers on the server (for app timeouts/etc).
Upvotes: 3
Views: 952
Reputation: 208
Here's an example of solving your particular problem by using an AuthenticationService and a CanActivate route guard. The below Guard can be bound to whatever route (page) you please, be it one or all of them.
@Injectable()
class AuthenticationService {
constructor () { }
isLoggedIn() {
// check your cookie logic here
}
}
@Injectable()
class AuthenticationGuard implements CanActivate {
constructor(private authenticationService: AuthenticationService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authenticationService.isLoggedIn()
.pipe(
tap(loggedIn => {
if (!loggedIn) {
this.router.navigate(['/login'], {
queryParams: {
nextUrl: state.url
}
});
}
})
);
}
}
@NgModule({
...
imports: [
RouterModule.forRoot([
{ path: 'dummyRoute/', loadChildren: './components/dummyModule/dummy.module#DummyModule', canActivate: [ AuthenticationGuard ] },
])
],
...
})
export class AppModule {}
While using AppComponent to run code on every page is a solution, I would only recommend it as a last resort. For the most part, Guards (used for authorising navigation steps), Resolvers (used for retrieving data required by the page prior load) and Interceptors (used to alter / filter HttpClient requests) used in conjunction with Services provide you with a more elegant way to solve these problems and keep your codebase neatly organised.
More on guards here https://angular.io/guide/router#guards.
A full example of an authentication guard implementation: https://angular.io/guide/router#canactivate-requiring-authentication
Upvotes: 0
Reputation: 1027
For authenticating Http requests you can you HttpInterceptors to append a token to each request for your API. Something like this ->
my-http.interceptor.ts
@Injectable()
export class MyHttpInterceptor implements HttpInterceptor {
constructor() {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = 'my_token'; // retrieve token from your storage.
const req = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(req).do((event: HttpEvent<any>) => {
// success
if (event instanceof HttpResponse) {
}
}, (err: any) => {
// failure
if (err instanceof HttpErrorResponse) {
}
});
}
}
Then register your http interceptor on either your CoreModule or AppModule.
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: MyHttpInterceptor, multi: true}
]
RouteGuards can be used to block certain routes for any reason you want - User isn't authorized, User doesn't have the proper role to access, ect...
https://codecraft.tv/courses/angular/routing/router-guards/
If you want to execute logic on Route change you can listen in on the router.events.
How to detect a route change in Angular?
Edit: As other people in this thread pointed out, always put business logic in a service.
For a best practice angular app structure -> https://itnext.io/choosing-a-highly-scalable-folder-structure-in-angular-d987de65ec7
Upvotes: 1
Reputation: 27
I would use Angular service and i would call it from app.component
It Says
Services are a great way to share information among classes that don't know each other.
Upvotes: -1
Reputation: 21367
you can create an authentication service (auth.service.ts) in your app and make it singleton, that service will contain all auth operation like (login, logout, getProfile...) after that you can inject that service and use it everywhere in your app when needed.
i recommend that you separate your app into modules and create a module for authentication.
and for everything shared you can create a shared module that contains shared components, services, pipes, interceptors ...
Upvotes: 0
Reputation: 426
you should put that logic in the app.components.ts
import { Component } from "@angular/core";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
// here goes your logic
}
Upvotes: 1