Distinguishing Literal and Parameterized Routes in Angular 6

I've encountered a strange issue that I'm not sure how to handle. In my application, you can either view your public account or create a new one.

The Account and CreateAccount modules are standalone and lazy loaded in the routes.ts file.

export const routes: Array<Route> = [
  { path: '', component: WelcomeComponent, pathMatch: 'full'},
  { path: ':name', loadChildren: './account/account.module#AccountModule' },
  { path: 'create-account', loadChildren: './create-account/create-account.module#CreateAccountModule', pathMatch: 'full'},  
  { path: '**', redirectTo: ''}
];

To view your account, you need to enter your username and then you'll be directed to an overview of your account. The URL should look like this:

https://baseurl.com/*accountName*/*someView*

The routes for the Account module are as follows:

export const routes: Array<Route> = [
  { path: '', component: AccountComponent, canActivateChild: [AccountGuardService], children: [
    { path: '', component: OverviewComponent },
    { path: 'transfer', component: TransferComponent, canActivate: [DeletedGuardService] },
    { path: 'voting', component: VotingComponent, canActivate: [DeletedGuardService] },
    { path: 'vesting', component: VestingComponent, canActivate: [DeletedGuardService] }
  ] },
]

If you want to create a new account, you can do so as a 'logged in' user and have full control over your child accounts or create a new one. The difference lies in the URL parameter:

https://baseurl.com/create-account/*accountName*
- creates a child account
https://baseurl.com/create-account
- creates a new account

The CreateAccount component acts as a wizard using @ngrx/store for navigation. The AccountName URL parameter specifies the starting point in the wizard.

The routes for the CreateAccount module are:

export const routes: Array<Route> = [
  { path: '', component: CreateAccountComponent, canDeactivate: [CreateAccountGuardService] },
  { path: ':account', component: CreateAccountComponent, canDeactivate: [CreateAccountGuardService] },
];

Prior to refactoring the project to use lazy loaded modules, everything worked fine. However, with this configuration, no matter what URL I use, I'm always redirected to the root and the CreateAccountComponent is displayed.

https://baseurl.com/*accountName*
-> https://baseurl.com/

https://baseurl.com/*accountName*/transfer
-> https://baseurl.com/

https://baseurl.com/create-account
-> https://baseurl.com/

https://baseurl.com/create-account/*accountName*
-> https://baseurl.com/

How can I differentiate between the literal route create-account and the parameterized route :name? Using pathMatch: full in various places hasn't helped. My understanding of routing still needs improvement.

This is how the route looked before refactoring:

export const routes: Array<Route> = [
  { path: '', component: WelcomeComponent, pathMatch: 'full'},
  { path: 'create-account', component: CreateAccountComponent, canDeactivate: [CreateAccountGuardService], pathMatch: 'full' },
  { path: 'create-account/:account', component: CreateAccountComponent, pathMatch: 'full', canDeactivate: [CreateAccountGuardService] },
  { path: ':name', component: AccountComponent, canActivateChild: [AccountGuardService], children: [
    { path: '', component: OverviewComponent },
    { path: 'transfer', component: TransferComponent, canActivate: [DeletedGuardService] },
    { path: 'voting', component: VotingComponent, canActivate: [DeletedGuardService] },
    { path: 'vesting', component: VestingComponent, canActivate: [DeletedGuardService] }
  ] },
  { path: '**', redirectTo: ''}
];

EDIT: The cause of the problem was found in Routes.Module.ts. I forgot to remove a module that is no longer imported but rather lazy-loaded (CreateAccountModule).

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { SharedModule } from '../shared/shared.module';

import { CreateAccountModule } from './create-account/create-account.module';

import { routes } from './routes';
import { WalletComponent } from './wallet/wallet.component';


@NgModule({
  imports: [
    SharedModule,
    /*CreateAccountModule - removing this import fixes the problem with routing override. Routing now works. */
    RouterModule.forRoot(routes),
  ],
  declarations: [
    WalletComponent, 
  ],
  exports: [
    RouterModule
  ]
})
export class RoutesModule { }

Answer №1

In order to improve the routing structure of your project, consider rearranging the order of the routes as shown below. By placing the 'create-account' route before the ':name' route, you can potentially enhance the user experience.

export const routes: Array<Route> = [
{ path: '', component: WelcomeComponent, pathMatch: 'full'},
{ path: 'create-account', loadChildren: './create-account/create-account.module#CreateAccountModule', pathMatch: 'full'},  
{ path: ':name', loadChildren: './account/account.module#AccountModule' },
{ path: '**', redirectTo: ''}
];

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilize cypress to analyze the loading time of a webpage

My current challenge involves using cypress to carry out website tests. I am looking for a reliable method to measure the duration it takes for certain cypress commands to load or execute. As an example: //var startTime = SomeStopwatchFunction(); cy.visit( ...

Exploring advanced customization options in Angular 6+: Extending the default configuration beyond the environment settings

I am dealing with multiple Angular configurations and I'm trying to customize the default settings by using lodash merge: import { merge } from 'lodash' import { defaults } from './defaults' export const customConfig = merge(defa ...

Issue with ambient contexts error in TypeScript constructor

What is the correct way to create a constructor in TypeScript? I have been researching and trying different approaches, but it seems like the syntax has changed. Here is my latest attempt: car.d.ts declare class Car { constructor(public engine: string ...

What is the title of the commonly used state management approach in rxjs? Are there any constraints associated with it?

When working with Angular applications, it is common to use the following approach to manage shared states: import { BehaviorSubject } from 'rxjs'; interface User { id: number; } class UserService { private _users$ = new BehaviorSubject([]) ...

Refresh your webpage automatically using Typescript and Angular

Currently facing an issue and seeking assistance. My query is regarding reloading a website after 5 minutes in a Typescript/Angular application. Can anyone help with this? ...

Testing Angular Components Using HostListener

I am looking to write unit tests for @HostListener, but I'm unsure of how to go about it since it's located on top of the component. Here is an example of the code: @HostListener('document:click', ['$event']) onDocumentClick ...

Stopping HTTP redirection in Angular 2

Attempting to simulate user login using Angular2 Http. Let's describe the situation below. There is a PHP application where users can log in through http://sample.com/login.php URL (a form exists with username and password input, users must fill in ...

What is the best way to access the ngClass value in an Angular test?

Here is the content of my component.html file with the ngClass attribute used in the second span element: <span class="container"> <button mat-icon-button [disabled]="disabled" (click)="onButtonClicked()"> <mat-icon>{{ico ...

Developing desktop applications with Angular 2 using NWjs

Looking to create an Angular 2 Desktop App using NWjs. Where can I find the entry point? Could someone provide some examples of developing Angular 2 Desktop Apps with NW.js? ...

Is it possible to deactivate the error message related to "Unable to ascertain the module for component..."?

I recently incorporated a new component into my TypeScript2+Angular2+Ionic2 project. Right now, I have chosen not to reference it anywhere in the project until it is fully developed. However, there seems to be an error thrown by Angular/ngc stating "Cannot ...

Expand the font manually

Is there a way to define a type that represents the widened version of another type? Consider the following scenario: function times<A extends number, B extends number>(a: A, b: B): A & B; The intention behind this times function is to preserv ...

Runtime AbstractControl in Angular 2

Following the guidance provided in this answer here, I attempted to incorporate an "Add more" feature into my Angular 2 application. The associated project can be found on this link. However, in order to initialize the project, I had to temporarily comment ...

Combining subscriptions in Angular

For the ngOnInit of a specific component, I have a need to subscribe to two different actions: To make a get request using an already existing Angular service that will return a list of items (sourceOptions in the code). To retrieve the route.queryParams ...

TypeScript requires that the `includes` function must have the same type parameter for both input and

When working with TypeScript, I've encountered an interesting dilemma regarding the use of the Array.Prototype.includes function. It seems that this function requires me to pass in the same type as in the original array, but isn't the purpose of ...

Unexpected outcome when returning a map

Encountered a puzzling issue that requires immediate clarification. When I input the following code into my project: this.metadata = json.metadata.map((x) => {return new Metadatum(x);}); console.log(this.metadata[0].value); The output consistently sho ...

I'm looking for ways to incorporate TypeScript definition files (.d.ts) into my AngularJS application without using the reference path. Can anyone provide

I'm interested in leveraging .d.ts files for enhanced intellisense while coding in JavaScript with VScode. Take, for instance, a scenario where I have an Angular JS file called comments.js. Within comments.js, I aim to access the type definitions prov ...

Executing POST calls to a Google Apps Script

Everything was running smoothly. I managed to set up an endpoint using Google Apps Script that allowed end users to send a message to me (or another contact) and receive a copy of that message as well. The code for the POST request looked something like ...

Understanding how to extract a specific value key from a JSON object in Typescript while utilizing Angular can greatly

I'm currently facing a challenge in Typescript with Angular where I need to retrieve a specific value from a JSON constant. While I am aware of the performance implications, I am wondering if there is a more efficient way to access this value within t ...

Using Angular 2 with the firebase-admin sdk

Whenever I attempt to integrate the firebase-admin SDK into my Angular2 project, an error occurs: ERROR in ./~/firebase-admin/lib/auth/token-generator.js Module not found: Error: Can't resolve 'jsonwebtoken' in '/home/koucky/git_projec ...

Discovering identical objects in two arrays in Angular using TypeScript is a breeze

I've hit a roadblock with a TypeScript problem in my Angular service. I have an array of ingredients: private ingredients: Ingredient[] = [ new Ingredient('farina', 500), new Ingredient('burro', 80), new Ingredient('ucc ...