Search code examples
angularangular-standalone-components

Angular 16 standalone url always routs to home page


My Angular 16 app is pure standalone, no ng modules at all. I configured routes, and when used within components as links (e.g.: routerLink="/team") it routes to the correct page, and the URL changes accordingly. However, trying to reach a page directly from the URL (for example, by just refreshing the localhost:4200/team page) - renders the home page. The URL does not even change - /team still appears as the URL, but the rendered page is the home page.

These are the relevant files:

app.component.html:

<app-top-nav></app-top-nav>
<router-outlet></router-outlet>
<app-footer></app-footer>

(If I remove the app-top-nav and app-footer, then the behavior does not change, only the URL indeed changes to /home as well).

app.component.ts:

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router, RouterOutlet } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';
import { DatabaseService, EmailService } from 'src/app/services';
import { UnsubscribeGroup } from './interfaces/unsubscribe-group.enum';
import { FilterMatchMode, PrimeNGConfig } from 'primeng/api';
import { TopNavComponent } from "./components/top-nav/top-nav.component";
import { FooterComponent } from "./components/footer/footer.component";
import { CookieHandlerService} from "./services/cookie.service"

@Component({
    selector: 'app-root',
    standalone: true,
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss'],
    imports: [CommonModule, RouterOutlet, HttpClientModule, TopNavComponent, FooterComponent]
})
export class AppComponent {

  constructor(private databaseService: DatabaseService, private emailService: EmailService, private cookie: CookieHandlerService, public primengConfig: PrimeNGConfig, private router: Router) {}

  async ngOnInit() {
    this.primengConfig.ripple = true;
    
    this.primengConfig.zIndex = {
      modal: 1100,    // dialog, sidebar
      overlay: 1000,  // dropdown, overlaypanel
      menu: 1000,     // overlay menus
      tooltip: 1100   // tooltip
    };

    this.primengConfig.filterMatchModeOptions = {
      text: [FilterMatchMode.STARTS_WITH, FilterMatchMode.CONTAINS, FilterMatchMode.NOT_CONTAINS, FilterMatchMode.ENDS_WITH, FilterMatchMode.EQUALS, FilterMatchMode.NOT_EQUALS],
      numeric: [FilterMatchMode.EQUALS, FilterMatchMode.NOT_EQUALS, FilterMatchMode.LESS_THAN, FilterMatchMode.LESS_THAN_OR_EQUAL_TO, FilterMatchMode.GREATER_THAN, FilterMatchMode.GREATER_THAN_OR_EQUAL_TO],
      date: [FilterMatchMode.DATE_IS, FilterMatchMode.DATE_IS_NOT, FilterMatchMode.DATE_BEFORE, FilterMatchMode.DATE_AFTER]
    };

this.router.navigate(['/home']);
  } 
}

Trying to remove the last line: this.router.navigate(['/home']); has no effect.

main.ts:

import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { environment } from 'src/environments/environment';
import { enableProdMode, importProvidersFrom  } from '@angular/core';
import { 
  PreloadAllModules, 
  provideRouter, 
  withDebugTracing, 
  withPreloading, 
  withRouterConfig 
} 
from '@angular/router';
import { appConfig } from './app/app.config';

if (environment.production) {
  enableProdMode();
}

bootstrapApplication(AppComponent, appConfig)
  .catch((err) => console.error(err));

app.config:

import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { 
  PreloadAllModules, 
  provideRouter, 
  withDebugTracing, 
  withPreloading, 
  withRouterConfig 
} 
from '@angular/router';
import { provideHttpClient } from '@angular/common/http';


import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes), provideHttpClient() ]
};

app.routes:

import { Routes } from '@angular/router';
import { HomeComponent } from './pages/home/home.component';
import { TeamComponent } from './pages/team/team.component';
import { SignupComponent } from './pages/signup/signup.component';
import { TermsComponent } from './pages/terms/terms.component';
import { PrivacyComponent } from './pages/privacy/privacy.component';

export const routes: Routes = [
    { path: 'home', component: HomeComponent }, 
    { path: 'signup', component: SignupComponent }, 
    { path: 'team', component: TeamComponent }, 
    { path: 'terms', component: TermsComponent },  
    { path: 'privacy', component: PrivacyComponent },  
    { path: '', redirectTo: 'home', pathMatch: 'full' },
    { path: '**', redirectTo: 'home' }
];

index.html:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>MyDreamTeam</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>

What am I missing, please?


Solution

  • In my top-nav.component.ts, I was importing this module:

    import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    

    Removing this import (from the imports array of the component) - solved the problem!

    You can see this in the stackblitz provided above. URL:

    https://stackblitz.com/edit/stackblitz-starters-kvfyb5?file=src%2Fmain.ts

    https://stackblitz-starters-kvfyb5.stackblitz.io/

    Remove the BrowserAnimationsModule import in the top-nav component - and the problem goes away. This works in my local implementation as well now.

    In Stackblitz, you can see that the console throws this error if this import exists:

    Error: NG05100: Providers from the BrowserModulehave already been loaded. If you need access to common directives such as NgIf and NgFor, import theCommonModule instead.
    

    Problem is, in my local setup, this error is not showing in the console, so I had no idea! So, couple of takeaways:

    1. Some errors are not showing locally, while they do show in Stackblitz.
    2. This BrowserAnimationsModule probably conflicts with something and cannot be used in some situations. See in Stackblitz...