How to Handle Routes for Module from NPM - javascript

I have an Angular module that I'm loading from an NPM module. How do I load the routes from it? Here is a snippet from my app.module.ts file:
import { HelloWorldModule } from 'hello-world-app-npm/hello-world-app.umd.js'; // The module loaded from NPM
const routes = [
{ path: 'hw', loadChildren: () => HelloWorldModule },
{ path: '', component: AppComponent },
]
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HelloWorldModule,
FormsModule,
HttpModule,
RouterModule.forRoot(routes)
],
exports: [RouterModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Here is how I've define my hello world module:
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { HelloWorldComponent } from './hello-world.component';
export const routes = [{ path: '', component: HelloWorldComponent }]
#NgModule({
bootstrap: [HelloWorldComponent],
declarations: [
HelloWorldComponent
],
imports: [
RouterModule.forChild(routes)
]
})
export class HelloWorldModule {
}
When I go to "/hw" I get an error in chrome saying
Uncaught (in promise): RangeError: Maximum call stack size exceeded
What am I doing wrong? How do I fix this?

I suspect it could be because of two things.
HelloWorldModule should not be appear inside AppModule import.
bootstrap: [HelloWorldComponent] inside HelloWorldModule is unnecessary.

Related

Regarding not loading component in order Angular with Lazyload Routing

I am using lazyload routing in our application! I'm facing strange issue as follows
I have AppModule in side that TopModule and then DashboardModule and all are loaded in lazyload
if someone open localhost:4200/dashboard then it loads in order of Appmodule,Topmodule DashboardModule and TopComponent
but it should loads in order of Appmodule,Topmodule,TopComponent and DashboardModule
As Dashboard Module is getting loaded Before TopComponent because of it my page is getting stucked!
NOTE : I have used in all modules where routing are defined!
My code is as follows
app.module.ts
import { CommonModule } from '#angular/common';
import { NgModule } from '#angular/core';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { RouterModule, Routes} from '#angular/router';
import { AppComponent } from './app.component';
import { BrowserModule } from "#angular/platform-browser";
const appRoutes: Routes = [
{
path: '',
loadChildren: './top.module#TopModule',
}
];
#NgModule({
declarations: [
AppComponent
],
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
RouterModule.forRoot(appRoutes)
],
providers: [],
entryComponents: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
app.component.html
<router-outlet></router-outlet>
top.module.ts
import { CommonModule } from '#angular/common';
import { NgModule } from '#angular/core';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { RouterModule, Routes} from '#angular/router';
import { TopComponent } from './top.component';
import { BrowserModule } from "#angular/platform-browser";
const appRoutes: Routes = [
{
path: '',
component: TopComponent,
children: [
{
path: '',
loadChildren: './first.module#FirstModule',
},
{
path: 'dashboard',
loadChildren: './dashboard.module#DashboardModule',
},
]
}
]
#NgModule({
declarations: [
TopComponent
],
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
RouterModule.forChild(appRoutes)
],
providers: [],
entryComponents: [],
})
export class TopModule {
}
top.component.html
<router-outlet></router-outlet>
First of all, as you stated in comment above, if TopComponent should appear in all view, it doesn't make sense to load it lazyly. You should add TopModule to your AppModule because users will get it no matter the url they enter.
Next, to load FirstModule and DashboardModule lazyly you can do it as below:
const appRoutes: Routes = [
{
path: '',
component: OutletComponent,
children: [
{
path: '',
loadChildren: './first.module#FirstModule',
},
{
path: 'dashboard',
loadChildren: './dashboard.module#DashboardModule',
},
]
}]
And finally create a component for childrens routing:
//OutletComponent
#Component({
selector: 'outlet-component',
template: `<router-outlet></router-outlet>`,
})
export class OutletComponent {}

Navigation change url, but not view

I have an angular application with a login component
this component is under app/main/login
I want to go to it from app.component.html via the button
Here is my app-routing.module code
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { LoginComponent } from './main/login/login.component';
const routes: Routes = [
{ path: 'main', children: [{ path: 'login', component: LoginComponent }] },
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Here is how I try to use route <button mat-raised-button class="btn-default" [routerLink]="['/main/login']">Log in</button>
Here is app.module.ts code
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import {MatButtonModule} from '#angular/material/button';
import {MainModule} from './main/main.module'
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
MatButtonModule,
MainModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
and here is main.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { LoginComponent } from './login/login.component';
#NgModule({
declarations: [LoginComponent],
imports: [BrowserModule],
providers: [],
bootstrap: [],
})
export class MainModule {}
When I click the button, the URL changing to http://localhost:4200/main/login but the view not changed.
How I can fix this?
Looking at your code it seems that you are trying to load component using lazy-loading technique.
So in AppRoutingComponent.ts file, instead of what your code replace it with :
const routes: Routes = [
{ path: 'main', loadChildren: '(path to main module)/main.module#MainModule' },
];
In layman terms this just tells the parent routing module to load the main.module when main path is encountered
Now In Main.module, configure child routes as:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { LoginComponent } from './login/login.component';
const routes: Routes = [
{ path: 'login', component: LoginComponent }
];
#NgModule({
declarations: [LoginComponent],
imports: [
BrowserModule,
RouterModule.forChild(routes) // Register routes for child module via forChild function instead of for Root
],
providers: [],
bootstrap: [],
})
export class MainModule {}

Uncaught (in promise): Error: Cannot match any routes (Angular8)

I maked my angular-app. All good works. But for deploy to server I getting error:
Uncaught (in promise): Error: Cannot match any routes. URL Segment:
'myUrl/app.aspx'
After build prod my app doesn't work either (I set base href and all files load, but I getting warning Unhandled Navigation Error).
I make difficult routing for my app.
I using submodules for routing. And I think the problem related with APP_BASE_HREF or wrong routing for my app/submodules.
My example:
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule } from "#angular/common/http";
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { NbThemeModule, NbLayoutModule, NbSidebarModule, NbButtonModule, NbTabsetModule, NbCardModule } from '#nebular/theme';
import { NbEvaIconsModule } from '#nebular/eva-icons';
import { AppRoutingModule } from './app-routing.module';
import { RouterModule } from '#angular/router';
import { MainModule } from './components/main/main.module';
import { AddModule } from './components/add/add.module';
import { APP_BASE_HREF } from '#angular/common';
#NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
NbThemeModule.forRoot({ name: 'default' }),
NbLayoutModule,
NbEvaIconsModule,
NbSidebarModule.forRoot(),
NbButtonModule,
NbTabsetModule,
NbCardModule,
AppRoutingModule,
MainModule,
AddModule,
HttpClientModule,
],
providers: [{ provide: APP_BASE_HREF, useValue: '/' }],
bootstrap: [AppComponent]
})
export class AppModule { }
I don't have providers: [{ provide: APP_BASE_HREF, useValue: '/' }] and all good works. But for deploy I geted error message:
Please provide a value for the APP_BASE_HREF token or add a base
element to the document.
I add APP_BASE_HREF and error disappeared.
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
const routes: Routes = [
{
path: '',
loadChildren: './components/main/main.module#MainModule'
},
{
path: 'event',
loadChildren: './components/event/event.module#EventModule'
},
{
path: 'add',
loadChildren: './components/add/add.module#AddModule'
},
{
path: 'archive',
loadChildren: './components/archive/archive.module#ArchiveModule'
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule { }
main-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { ViewEventsComponent } from './view-events/view-events.component';
const routes: Routes = [
{
path: '',
component: ViewEventsComponent,
},
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MainRoutingModule { }
event-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { EventPageComponent } from './event-page/event-page.component';
const routes: Routes = [
{
path: ':id',
component: EventPageComponent,
},
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class EventRoutingModule { }
And I noticed:
after build app - generated files of module: archive and event, but don't generated file for main-module.
I solved this problem with fixed in app-routing.module.ts. A added { useHash: true }:
#NgModule({
imports: [RouterModule.forRoot(routes, { useHash: true })],
exports: [RouterModule],
})

How to import a component into two pages?

I have a structure like this:
home - page
home2 - page
test-component - component
I need to be able to use the component(<app-test-component></app-test-component>) on both pages.
If I just use the tag:
ERROR Error: Uncaught (in promise): Error: Template parse errors:
'app-test-component' is not a known element:
If I just import (import {TestComponentComponent} from '../test-component/test-component.component') into home.module.ts and put it in the module import:
core.js:9110 ERROR Error: Uncaught (in promise): Error: Unexpected
directive 'TestComponentComponent' imported by the module
'HomePageModule'. Please add a #NgModule annotation.
A similar error if added to declarations.
Git.
How to import a component on both pages and use?
There are few changes that you should make:
You should not import component as I can see in the code.
Rearrange the project structure, and move reusable component such as TestComponent into a shared component. To give you an example, I'll give below example where I have created shared module names as TestModule
/app
/home
-home.component.ts
-home.module.ts
/test
-test.component.ts
-test.module.ts
-app.component.ts
-app.module.ts
app.module.ts
#NgModule({
declarations: [AppComponent],
imports: [BrowserModule, HomeModule, RouterModule.forRoot([{ path: '', component: HomeComponent }])],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
test.module.ts
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { TestComponent } from './test.component';
#NgModule({
declarations: [TestComponent],
exports: [TestComponent],
imports: [CommonModule],
})
export class TestModule {}
home.module.ts
#NgModule({
declarations: [HomeComponent],
exports: [HomeComponent],
imports: [
CommonModule,
TestModule
]
})
export class HomeModule { }
This set of project structure would certainly help you to reuse test.module features. Let me know if you need more code.
Declare TestComponentComponent only in home.module.
home.module.ts
#NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
RouterModule.forChild([
{
path: '',
component: HomePage
}
])
],
declarations: [HomePage, TestComponentComponent]
})
export class HomePageModule {}
app.module.ts
#NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
providers: [
StatusBar,
SplashScreen,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule {}

Application routing overrides modules routing

I've met some interesting situation while developing application using Angular 4.1.1. I've always declared routing in a module and I do it in all modules.
For example, new-cars.routing.module.ts:
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { NewCarsComponent} from './new-cars.component';
import { NewCarsResolver } from './new-cars.resolver';
#NgModule({
imports: [
RouterModule.forChild([
{
path: 'cars/:id',
component: NewCarsComponent,
resolve: {
card: NewCarsResolver
}
}
])
],
exports: [RouterModule]
})
export class NewCarsRoutingModule { }
Then I've read this article to redirect to "404 Not Found" component, if user inputs not exisiting URL address. And I declared this route in app-routing.module.ts:
export const routes: Routes = [
{ path: '**', component: PageNotFoundComponent }
];
and now all pages show Page not found.
app.module.ts:
import ...;
import { NewCarsModule } from './new-cars/new-cars.module';
import ...;
#NgModule({
imports: [
RouterModule,
BrowserModule,
AppRoutingModule,
HomeModule,
SearchModule,
CoreModule,
NewsCarsModule,
],
declarations: [
AppComponent,
PageNotFoundComponent
],
bootstrap: [AppComponent]
})
export class AppModule { }
My questions is Is it possible to write { path: '**', component: PageNotFoundComponent } just in one place, not in all components?
The main problem here is the order of your routes.
#NgModule({
imports: [
...
NewsCarsModule, // this order is important
AppRoutingModule // where you declared PageNotFoundComponent
],
...
})
export class AppModule {}
See also
https://github.com/angular/angular/issues/12648

Categories

Resources