Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I want to get and save user interaction with angular app,
and app interactions with the APIs the add this log to a file.
If I understood your question correctly, you can write common logic on one place for user page navigation and API call.
For page navigation, subscribe to router events. Ex.
constructor(router:Router) {
router.events.subscribe(event => {
if(event instanceof NavigationStart) {
}
if(event instanceof NavigationEnd) {
// log record to file here --> 'user navigated to XYZ page.'
}
// NavigationCancel
// NavigationError
// RoutesRecognized
}
});
For API calls, you can implement HTTP interceptor.
#NgModule({
...
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptorService,
multi: true
}]
})
export class AppModule { }
#Injectable()
export class MyInterceptor implements HttpInterceptor {
intercept( req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// log record to file --> 'calling api {url}'
return next.handle(req);
}
}
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed last year.
Improve this question
I`m doing a project with react and I decided to make routes functionality a little different, I put the routes details to an separated file as an array: , and on the routes component I iterate through the array using the map function:
. But I don't know if what I did is something recommended, do you think it's better to put the routes in a static way directly in the component or is there a better solution?
It is better to use the useRoutes function provided by the react-router-dom package.
This makes your code shorter and authentication can be added easily using this procedure.
This way, you can define the main routes as an object like:
routes = (loggedIn) => [
{
path: '/',
children: [
// unprotected routes here
]
},
{
path: '/main',
element: loggedIn ? <Layout /> : <Navigate to='/login' />
children: [
// protected routes here
]
}
]
Then return useRoutes in the route component like:
const { loggedIn } = useSelector((state) => state.auth);
return useRoutes(routes(loggedIn), '');
useRoutes API: https://reactrouter.com/docs/en/v6/api#useroutes
I am trying to fix an issue users are having after impersonating as a different user in the system. Currently, a regional user could impersonate as someone else which does not load the full content of the page as they now have to press F5 to see everything on this page. I tried to reproduce this issue by pointing to the same database in local but not able to do so. When I go to the DEV url for instance, I then try impersonating as a different user which then loads the page partially and refreshing the page (F5), I see the entire content. I believe this is happening due to the route navigate, not sure if I am missing anything to pass in this function.
this.router.navigate(['/', user.Company.Abbreviation.toLowerCase()]);
This is the full function that the Impersonate button is executing.
setImpersonatation() {
this.store.dispatch(new AuditSearchClearAction());
this.store.dispatch(new CompanyChangedAction(this.impersonationForm.value.company, null));
const user = this.impersonationForm.value.user as UserLogin;
this.store.dispatch(new BaseUserSetAction(user as User));
this.store.dispatch(new AuthorizeAction(user));
this.router.navigate(['/', user.Company.Abbreviation.toLowerCase()]);
this.store.dispatch(new MyWorkSetLetterReminderUserAction(user.UserId));
}
When I switch a user, I get the screen below.
But when I refresh the page (F5), then i see the entire data.
Do I need to add any parameters to the router.navigate so it loads the page correctly? Seems like something is missing of when trying to load the page after the Impersonate button is clicked.
Thanks!
UPDATE:
setImpersonatation() {
this.store.dispatch(new AuditSearchClearAction());
this.store.dispatch(new CompanyChangedAction(this.impersonationForm.value.company, null));
const user = this.impersonationForm.value.user as UserLogin;
this.store.dispatch(new BaseUserSetAction(user as User));
this.store.dispatch(new AuthorizeAction(user));
this.store.dispatch(new MyWorkSetLetterReminderUserAction(user.UserId));
**this.changeDetector.detectChanges();
this.router.navigate(['/', user.Company.Abbreviation.toLowerCase()]);**
}
Using a resolver is always a good choice in cases that data is not ready to generate the page UI.
Resolver is preventing your app from navigate unless the data is fetched completely from server.
Steps:
create a resolver service by running this command:
ng generate resolver test-resolver
you have to put your ajax call in the resolve method of resolver:
#Injectable({ providedIn: 'root' })
export class TestResolver implements Resolve<Hero> {
constructor(private service: TestService) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any>|Promise<any>|any {
return this.service.testAjax();
}
}
you have to define your resolver in your routing module:
#NgModule({
imports: [
RouterModule.forRoot([
{
path: 'test',
component: TestComponent,
resolve: {
test: TestResolver
}
}
])
],
exports: [RouterModule]
})
export class AppRoutingModule {}
you have to catch the response in your component (in this case TestComponent):
#Component({
selector: 'app-test',
template: ``
})
export class TestComponent {
constructor(private activatedRoute: ActivatedRoute) {
this.activatedRoute.data.subscribe((data) => {
console.log(data.test);
});
}
}
In this way you will navigate to the next page ONLY if data is fully loaded and this feature makes it so much easier to implement a better user experience like a loading on navigation to those pages that require some data to be fetched.
scenario :
Here i am building an application in which currently i have a page called products-info where a url is sent to the customer and on clicking on the link he can directly open that particular product page and see the info and the same page will be there in application.
issue :
Here i am protecting the routes using Auth guards so without logging, a user cannot access the page .If i sent the same page url to user via email he should be able to view only the page.
So my application has:
login page
products page
products-info page
Normally if a user logs in, this page will be visible but when an admin sends a url as mobiledot.com/products-info to user's email, user clicks on that and application don't want to login and it doesn't want to show any logout or other pages info only on that specific page. below is my code :
router.module.ts
const routes: Routes = [
{ path: '', component: LoginComponent },
{ path: 'main/:role', component: MainComponent, canActivate: [RouteGuard] },
{ path: 'admin', component: AdminComponent},
{ path: 'user', component: userComponent,canActivate: [RouteGuard]}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [RouteGuard]
})
export class AppRoutingModule { }
auth guard
#Injectable()
export class RouteGuard implements CanActivate {
constructor(private service: accessService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean> | Promise<boolean> {
const isAllowed = this.service.getAuthenticated();
if (!isAllowed) {
this.router.navigate(['/']);
}
return isAllowed;
}
}
So i also thought about some thing like if user logs into application. My router module is:
if(user loginin){
{ path: 'main/:role', component: MainComponent, canActivate: [RouteGuard] },
}
else {
{ path: 'main/:token', component: MainComponent },
ex: www.mobiledot.com/product-info?toke="ssdsdsdsdSDSD"
}
Is it possible or do we have any other way?
In short, if admin sent the same page url in application which is protected by auth guards to the user via email then user will click on the link and open the page and it should not ask for login.
There is another problem which is about stored token in localstorage. so before moving, do we have to clear that token and place a new one so that it will not redirect to main page?
You mean that products-info should be visible for registered users, as they can receive the corresponding link inside their email while they may be unauthorized (perhaps by token expiration) so you need a solution to cover it.
First of all, this is a bad practice to reveal sth like token as Url parameter. So avoid it.
Second, Please try to employ right solution instead of changing basic behaviors in your App. AuthGuard designed to decide if a route can be activated or not. It uses browser storage and in case of token expiration, You can only refresh it before expiration, otherwise user has to login again.
My solution is creating sth like a ticket id which can be appended to the sent link (like mobiledot.com/products-info/928f5f8b663571b7f3d829921c9079939c2d0319). You can make it one-time valid or more for users. store it in database and validate it when a user uses. In this way, there's no need to employ AuthGuard just control content permission on server-side.
As you have a route guard , you need a case where it's should return true even you are not logged in.
So, simply you can use the approach you have think of www.mobiledot.com/product-info?toke="ssdsdsdsdSDSD".
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean> | Promise<boolean> {
// check if there is a query param , like token in the url and url is your without token one.
if(queryParamToken && urlpath === 'view'){
// as you have token hit the api to check if required to check token is a valid one.
or can simply return true as per your need / requirement
-- checkout this link if you need referece
} else {
const isAllowed = this.service.getAuthenticated();
if (!isAllowed) {
this.router.navigate(['/']);
}
return isAllowed;
}
}
Verify token with API in Angular8 canActivate method of AuthGuard -- checkout this link if you need reference
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
What should we use, #Input & #Output decorators or Services in Angular? What would be the correct use case for each of the features?
I have read about one use case for each.
Higher class components --> Use Services
Lower class components (Closely related) ---> Use input and output decorators
Can anyone elaborate and explain to clarify?
#Input (Parent to Child Relationship) -> If you want to pass data from Parent to Child component for example
Component A is Parent and Component B is a child that time we will use #Input
decorator into child component which is B
// app.component.ts (Parent)
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
template: <div><child [count]="cnt"></child></div>
})
export class AppComponent {
cnt: number = 10;
}
// Child...
import { Component, Input } from '#angular/core';
#Component({...})
export class ChildComponent {
#Input()
cnt: number = 0;
}
#Output (Child to Parent Relationship) - When you want to pass data from child to parent with EventEmitter
#Output() public eventName:EventEmitter = new EventEmitter();
No relationship between components - Then used shared service to pass data from component A to Component Z
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I want to import a module I've created in the app to be loaded on a certain route which has it's own routing within
You need to have Routes.forChild(routes) in your custom modules' .module.ts file
then in your main routing load your module lazily
import { CustomModule } from 'your-path'
const routes: Routes = [
{
path: 'your-path', loadChildren: () => CustomModule
}
];
As of Angular 8 the new way to import child routes is this:
{path: "user", loadChildren: () => import("./users/user.module").then(m => m.UserModule)};
Angular team did this to be more consistent with next ES and also this will be understood by the IDEs, webpack, etc.
What Omair said is correct, however I'm answering as well for the sake of having options.
You can also do this, if you prefer:
import { CustomModule } from 'your-path'
const routes: Routes = [
{
path: 'your-path', loadChildren: 'src/app/path/to/your/module/custom.module#CustomModule'
}
];