Search code examples
angulartypescriptangular-routingangular-routerangular12

Angular navigate to same component from 2 different origins and display some different UI elements depending on navigation origin


I want to be able to navigate to the same component (DetailsComponent) from 2 other different components (Home and CategoryAppsComponent), and change a couple UI elements based on a flag/boolean prop, depending on when the navigation is coming from.

I got it working using the state prop of the Router navigate method like so:

On Home.ts and on CategoryAppsComponent.ts where the navigation happens, respectively:

this.router.navigate(["home", "details", id], { state: { categoryAppsHeader: false } });

this.router.navigate(["home", "details", id], { state: { categoryAppsHeader: true } });

And then on the DetailsComponent.ts I assign the value to a prop which I then use an ngIf on the respective HTML to show or hide the headers:

this.categoryAppsHeader = this.router.getCurrentNavigation().extras.state["categoryAppsHeader"]

This is the solution I found because although DetailsComponent is a direct child of HomeComponent on the routes, CategoryAppsComponent is not, so I can't just pass a property through the HTML.

However this created a problem - when I click on one of the cards of DetailsComponent (please refer to the routes.ts file down below), from either the Home page or the CategoryAppsComponent, and I refresh the page, Angular sends me to the Home page instead, as if the route did not exist (example route could be localhost:4200/home/details/123).

I guess this has to do with the state prop because before I implemented it, I had the refresh working.

The last route down below was me attempting to make it work with the data prop but I was unsuccessful, I left it in because maybe someone knows a solve using it.

routes.ts

export const routes: Route = {
path: `home`,
component: HomeComponent,
children: [
    {
        path: "details/:id",
        component: DetailsComponent,
    },
    {
        path: "categories",
        children: [
            {
                path: "",
                pathMatch: "full",
                component: CategoriesComponent,
            },
            {
                path: ":categoryId/apps",
                component: CategoryAppsComponent,
            },
            {
                path: "apps/:appId",
                component: DetailsComponent,
                data: {
                    categoryAppsHeader: true,
                },
        ],
    },
],};

I am sorry if the explanation is a bit confusing or if I haven't provided enough information, please let me know if you have any doubts about the implementation so that hopefully you can help me out. Any help is appreciated, thank you :)


Solution

  • Answering for future reference and in case anyone has the same doubt and understands my (bad) explanation up top:

    I managed to do what I wanted by fixing the last route as such:

    {
        path: ":categoryId/apps/:id",
        component: DetailsComponent,
        data: {
            categoryAppsHeader: true
        }
    },
    

    And then on DetailsComponent's constructor accessing the true flag and storing it on a variable like such (and using that boolean on the template):

    this.categoryAppsHeader = this.activatedRoute.snapshot.data["categoryAppsHeader"];
    

    P.S: Some bonus info, I managed to implement the "Go back" button by accessing the URL, splitting it into an array and removing the unwanted strings:

    this.router.navigate(window.location.pathname.split("/").slice(1, -1))
    

    Thank you