I have a module called "host" with its own routing that I want to insert into the app-routing.module. However, I have the problem of the wildcard loading first and displaying PageNotFoundComponent, instead of the Host component loading. I have the following files.
host.module.ts
....
const routes: Routes = [
{
path: 'host',
children: [
{ path: '', component: HostComponent }
]
}
];
#NgModule({
declarations: [HostComponent],
imports: [
CommonModule,
RouterModule.forChild(routes)
]
})
export class HostModule { }
app-routing.module.ts
const routes: Routes = [
{ path: '', component: HomeComponent, pathMatch: "full"},
{ path: '**', component: PageNotFoundComponent }
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.module.ts
#NgModule({
declarations: [
AppComponent,
HomeComponent,
PageNotFoundComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HostModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.html
<h2>Home</h2>
<ul>
<li>
<h2><a routerLink="/host">host</a></h2>
</li>
</ul>
<router-outlet></router-outlet>
Problem: When I run the app and click on the "Host" button, it loads the PageNotFoundComponent. I obviously want it to go to the HostComponent.
In your app.module.ts you need to reorder your imports
#NgModule({
declarations: [
AppComponent,
HomeComponent,
PageNotFoundComponent
],
imports: [
BrowserModule,
HostModule, <--- this before AppRoutingModule
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Reason being is because the order of the routes in the configuration matters. https://angular.io/guide/router#configuration
The ** path in the last route is a wildcard. The router will select this route if the requested URL doesn't match any paths for routes defined earlier in the configuration. This is useful for displaying a "404 - Not Found" page or redirecting to another route.
The order of the routes in the configuration matters and this is by design. The router uses a first-match wins strategy when matching routes, so more specific routes should be placed above less specific routes. In the configuration above, routes with a static path are listed first, followed by an empty path route, that matches the default route. The wildcard route comes last because it matches every URL and should be selected only if no other routes are matched first.
Related
x.componet.ts
const path="path1"
x.component.html
[routerLink]="['create',path]"
<router-outlet name="modal"></router-outlet>
modulex-routing.module.ts
const routes: Routes = [
{
path:'create',
children:[
{
path:'path1',component:path1Component,outlet:'modal'
},
{
path:'path2',component:path2Component,outlet:'modal'
},
],
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class HomeRoutingModule { }
app.routing.module.ts
const routes: Routes = [
{
path:'',
component:HomeComponent,
outlet:'home'
},
];
#NgModule({
imports: [RouterModule.forRoot(routes,{
preloadingStrategy: PreloadAllModules
})],
exports: [RouterModule]
})
app.module.ts
#NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
HomeRoutingModule,
AppRoutingModule,
HomeModule
],
providers: [
DatePipe
],
bootstrap: [AppComponent]
})
export class AppModule { }
ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'create/path1'
in modulex routing created some routes with respective components
and in app-routing using preloadmodule approach , when tries to access 'create/path1' it says
Error: Cannot match any routes.
am I Missing anything?
if remove outlet name everything works
When I select the initial component of the upload in my function module GalleryModuleModule this component GalleryComponent
I get this error:
Invalid configuration of route '': Array cannot be specified (all components are in the GalleryModuleModule). Tell me what am I doing wrong and how to solve this problem?
app.module:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { GalleryModuleModule } from './gallery-module/gallery-module.module';
#NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
GalleryModuleModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
app.component.html:
<div class="container">
<router-outlet></router-outlet>
</div>
gallery-module.module:
import {NgModule} from '#angular/core';
import {CommonModule} from '#angular/common';
import {GalleryComponent} from "./gallery/gallery.component";
import {GalleryAddComponent} from './gallery/gallery-add/gallery-add.component';
import {RouterModule, Routes} from "#angular/router";
const appRoutes: Routes = [
{path: '', redirectTo: '/gallery', pathMatch: 'full'},
{path: 'gallery-add', component: 'GalleryAddComponent'},
];
#NgModule({
imports: [
CommonModule,
RouterModule.forRoot([
appRoutes,
{enableTracing: true}
])
],
declarations: [GalleryComponent, GalleryAddComponent],
exports: [GalleryComponent, GalleryAddComponent RouterModule],
})
export class GalleryModuleModule {
}
You did {path: '', redirectTo: '/gallery', pathMatch: 'full'}, while in fact you dont have a path named gallery that should be redirected to.
For exemple changing your route configuration to:
const appRoutes: Routes = [
{path: '', redirectTo: '/gallery', pathMatch: 'full'},
{path: 'gallery', component: GalleryComponent},
{path: 'gallery-add', component: GalleryAddComponent},
];
and removing the extra array inside RouterModule.forRoot() (https://angular.io/api/router/RouterModule#forRoot) (as mentioned by #Suresh ) should work !
PS: do not forget to import the components listed in your route config (they should not be quoted as strings)
See, RouterModule.forRoot() needs to be defined only in App.module.ts which is the root router module. But you are defining those root routes in Your Child Module 'GalleryModuleModule' which is imported in to app.module.ts.
import {NgModule} from '#angular/core';
import {CommonModule} from '#angular/common';
import {GalleryComponent} from "./gallery/gallery.component";
import {GalleryAddComponent} from './gallery/gallery-add/gallery-add.component';
import {RouterModule, Routes} from "#angular/router";
const appRoutes: Routes = [
{path: '', redirectTo: '/gallery', pathMatch: 'full'},
{path: 'gallery-add', component: 'GalleryAddComponent'},
];
#NgModule({
imports: [
CommonModule,
RouterModule.forRoot(
appRoutes,
{enableTracing: true}
)
],
declarations: [GalleryComponent, GalleryAddComponent],
exports: [GalleryComponent, GalleryAddComponent RouterModule],
})
export class GalleryModuleModule {
}
I am creating an application that uses Angular 6 (6.0.6) and #uirouter/angular (2.0.0). But my app does not reconize the route '/login', it does only navigate to '/' (even if I remove the 'otherwise: '/'')
This application exists of multiple modules with multiple pages. The structure can be described as follows:
app/
-- home/
---- home.module.ts
---- home.component.ts
---- home.route.ts
---- home.scss
---- home.html
-- login/
---- login.module.ts
---- login.component.ts
---- login.route.ts
---- login.scss
---- login.html
-- app.module.ts
-- app.component.ts
Both modules have a separate routing file. The way I thought it would work was as follows (simplified example, don't mind the missing parts):
app.module.ts
#NgModule({
declarations: [AppComponent],
imports: [
UIRouterModule.forRoot({otherwise: '/'}),
HomeModule,
LoginModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
home.module.ts
#NgModule({
imports: [
UIRouterModule.forChild({states: [homeState]}),
NavbarModule
],
declarations: [HomeComponent],
providers: []
})
export class HomeModule {
}
home.route.ts
export const homeState: Ng2StateDeclaration = {
name: 'home',
url: '/',
component: HomeComponent
};
login.module.ts
#NgModule({
imports: [
UIRouterModule.forChild({states: [loginState]}),
],
declarations: [LoginComponent],
providers: []
})
export class LoginModule {
}
login.route.ts
export const loginState: Ng2StateDeclaration = {
name: 'login',
url: '/login',
component: LoginComponent
};
I expected that the UIRouterModule.forChild() method would just add the route to the configuration. But the /login route is not reconized and it just navigates back to /. I do not want to create a submodule where all my routing happens, because then I will also have to import all the dependencies my components have in that module (so far separation of concern and modularization).
This would look as follows for my example app:
const states = [homeState, loginState];
#NgModule({
imports: [
UIRouterModule.forChild({states: [states], otherwise: '/'}),
NavbarModule
],
declarations: [HomeComponent, loginComponent],
providers: []
})
export class AppRoutingModule {
}
The loginComponent does not need the NavBarModule, but still gets it this way..
Since this doesn't work I am clearly doing something wrong. Can anyone tell me what I am doing wrong and how I should fix it?
Your architecture may need a bit more thought. Have a look at the approach in this blog post which uses the native Angular router to achieve what you are trying to do.
I'm new in Angular 5 and trying to build an app with client side and admin side. So I did some search and made this:
AppRoutingModule
const appRoutes: Routes = [
{
path: '',
loadChildren: 'app/website/public.module#PublicModule'
},
{
path: 'admin',
loadChildren: 'app/admin/admin.module#AdminModule'
}
];
#NgModule({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
PublicRoutingModule
const PUBLIC_ROUTES: Routes = [
{
path: '',
component: HomeComponent,
}
];
#NgModule({
imports: [RouterModule.forChild(PUBLIC_ROUTES)],
exports: [RouterModule]
})
export class PublicRoutingModule { }
AdminRoutingModule
const ADMIN_ROUTES: Routes = [
{
path: '',
component: DashboardComponent,
data: {
title: 'Dashboard'
},
children: [
]
}
];
#NgModule({
imports: [RouterModule.forChild(ADMIN_ROUTES)],
exports: [RouterModule]
})
export class AdminRoutingModule { }
And I have imported AppRoutingModule in AppModule, and also imported PublicRoutingModule in PublicModule, also imported AdminRoutingModule in AdminModule.
When I run the app, there is no errors but the HomeComponent is not been rendered initially.
Can anyone tell what's the problem here? Thank you.
For lazy load module, I think you should add components' declarations to their own router module.
Example for PublicRoutingModule(same for AdminRoutingModule)
const PUBLIC_ROUTES: Routes = [
{
path: '',
component: HomeComponent,
}
];
#NgModule({
declarations: [ HomeComponent ], // add declaration
imports: [RouterModule.forChild(PUBLIC_ROUTES)],
exports: [RouterModule]
})
export class PublicRoutingModule { }
BTW, while debugging routing problems, you should enable tracing to see what really happened during navigation.
#NgModule({
imports: [RouterModule.forRoot(appRoutes, { enableTracing: true })],
exports: [RouterModule]
})
export class AppRoutingModule { }
I made a simple app which is running correctly.
Now I am trying to write test cases of that application, so I tried with routing.
stackblitz
My routing code is this
Main module:
export const routes: Routes = [
{ path: '', redirectTo: '/users', pathMatch: 'full' },
];
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
UserModule,
HttpClientModule,
RouterModule.forRoot(routes)
],
Feature module:
const routes: Routes = [
{path: 'users', component: ListingComponent}
];
#NgModule({
imports: [
CommonModule,
RouterModule.forChild(routes)
],
declarations: [ListingComponent]
})
Code
I try to run my spec but I am getting above error
describe('Initial navigation', () => {
it('default route redirects to home (async)', fakeAsync(() => {
router.initialNavigation(); // triggers default
fixture.detectChanges();
tick();
console.log('==================');
console.log(location.path());
// fixture.whenStable().then(() => {
expect(location.path()).toBe('/users');
// })
}));
});
If you import UserModule to the spec, this resolves the error. As AppModule modules imports UserModule to register user feature/module routes, it must also be imported in the spec to ensure it's route registrations are available in the spec as well.
The need for this is implied at a basic level in the documentation Testing: Import a feature module.
//setup
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
UserModule, // import module
RouterTestingModule.withRoutes(routes)],
declarations: [
TestComponent,
]
});
fixture = TestBed.createComponent(TestComponent);
router = TestBed.get(Router);
location = TestBed.get(Location);
});
Here is an updated StackBlitz demonstrating the functionality (test passing with no error).