0

I am wondering how to properly bite the routing topic in my application.

How it's look now: app-routing.module.ts file:

const routes: Routes = [
  {
    path: '',
    component: MainLayoutComponent,
    children: [
      {
        path: '',
        loadChildren: '../app/modules/home.module#HomeModule'
      },
      {
        path: '',
        loadChildren: '../app/modules/products.module#ProductsModule'
      }
    ]
  },
  {
    path: '**',
    redirectTo: '/404'
  }
];

I know its looking bad. Two same paths: ''. But in ProductsModule my routing looks like this:

products.routing.ts file:

const routes: Routes = [
  {
    path: 'products/:id',
    component: ProductDetailsComponent
  },
  {
    path: ':mainCategory',
    component: ProductsComponent
  },
  {
    path: ':mainCategory/:subCategory',
    component: ProductsComponent
  }
];

What im trying to do:

1.After go to: '/products/12331' load ProductDetailsComponent with id 12331.

Probably it's doesnt work because main module have path: ''.

Is the solution to this problem to separate the ProductDetailsComponent from the ProductsComponent?

In this way my app-routing.module.ts will looks:

const routes: Routes = [
  {
    path: '',
    component: MainLayoutComponent,
    children: [
      {
        path: '',
        loadChildren: '../app/modules/home.module#HomeModule'
      },
      {
        path: 'products',
        loadChildren: '../app/modules/products.module#ProductsModule'
      },
      {
        path: ':mainCategoryId',
        loadChildren: '../app/modules/products.module#CategoriesModule' (adding new module with CategoriesComponent)
      }
    ]
  },
  {
    path: '**',
    redirectTo: '/404'
  }
];

Second problem is that i'm loading categories from backend. How do I solve the problem of routing to a category that does not exist? For example i have categories:

  1. Foods [Drinks,Meats, Pizza's]
  2. Clothes [Shoes, Jackets, Hats]

Now if im route to:

/Foods/Drinks - should load CategoriesComponent

/Foods/Shoes - should route to /404 but how to handle it? (categories not exists)

/randomName/Drinks - should route to /404

How i can resolve it? Maybe my question's are stupid but im learning angular :)

1 Answer 1

1

You're asking two very different questions, which isn't ideal, but I'll try and help.

For the routing question, your 2nd routing table is better, but still isn't correct.

Using children for an empty path seems to defeat the purpose. You're also lazy loading HomeModule on a child route with an empty path. I'm pretty sure that doesn't work. If home.routing.ts actually contains child paths, just move this up to the top level as there's no need to lazy load those.

Try redoing it something like this:

const routes: Routes = [
    {
        path: '',
        component: MainLayoutComponent,
    },
    {
        path: 'home',   // pretending this is from home.module.ts
        component: HomeComponent,
    },
    {
        path: 'products',
        loadChildren: '../app/modules/products.module#ProductsModule'
    },
    {
        path: 'categories',
        loadChildren: '../app/modules/products.module#CategoriesModule'
    },
    {
        path: '**',
        redirectTo: '/404'
    }
];

This is much simpler and you'll have fewer issues getting everything up and running. I'd say it's generally a bad idea :mainCategoryId as a top level path unless you only have one type of thing. So putting them under categories/:mainCategory is going to be a lot easier to understand what's going on.

Now for your second question you wanted to know how to redirect to a 404 page if given an invalid category. Because we changed the route to categories/:mainCategory we don't need to worry about your /randomName/Drinks as it'll already go to the 404. For your other examples you have a couple ways to handle it.

Probably the simplest way would be to just check the params inside your ProductsComponent.

@Component({
    selector: 'products-component',
    templateUrl: './products-component.component.html',
    styleUrls: ['./products-component.component.scss'],
})
export class ProductsComponent {
    public category: string;
    public subCategory: string;

    constructor(private route: ActivatedRoute, private router: Router) {
        this.route.params.subscribe( params => {
            this.category = params['mainCategory'];
            this.subCategory = params['subCategory'];

            // validate categories in some way (either service, local method or something 
            if (!this.isCatValid(this.category) || !this.isCatValid(this.subCategory)) {
                this.router.navigate(['404']);
            }   
        }
    }

    this.isCatValid(category: string): boolean {
        // validate category
    }
}

Alternately if you create a categoryService that you can ensure pre-loads before any routes and has call resolves you could use add a CanActivate route guard to your categories routes. So your categories.routing.ts looks like this:

const routes: Routes = [
  {
    path: ':mainCategory',
    component: ProductsComponent,
    canActivate: [CanActivateCategories]
  },
  {
    path: ':mainCategory/:subCategory',
    component: ProductsComponent,
    canActivate: [CanActivateCategories]
  }
];

Then you just need to write a CanActivateCategories which validates the params and either returns true or if not valid just another this.router.navigate(['404']);

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.