I have ERROR in Cannot read property 'loadChildren' of null on npm run build prod --aot=true in my Angular 8 project. The local build works perfect.
I found, that this error appears when I'm trying to convert some object to Route by a special function, and after that add this route to Routes array.
Please help to understand how to fix it.
Some piece of code:
function objToRoute(obj: any): Route {
// convert it to route and return
}
const routes: Routes = [
path: '',
component: SomeComponent,
children: [
objToRoute(specialObject),
{
path: '**',
component: StubComponent
}
]
]
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class SomeRoutingModule {}
To be more specific, here is a simple example of objToRoute function:
function objToRoute(obj: any): Route {
return obj;
}
const routeObj: Route = {
path: 'somePath',
pathMatch: 'full',
loadChildren: () => import('pathToDir/someLazy.module').then(m => m.SomeLazyModule)
}
const routes: Routes = [
path: '',
component: SomeComponent,
children: [
objToRoute(routeObj),
{
path: '**',
component: StubComponent
}
]
]
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class SomeRoutingModule {}
And in this case I have the error ERROR in Cannot read property 'loadChildren' of undefined on npm run build prod --aot=true
Related
I configured my app in two levels for nested routing as shown in the snapshot image.
the content of app modules is:
app.module.ts
#NgModule({
declarations: [
AppComponent,
DashboardComponent,
TeacherMembershipComponent,
StudentMembershipComponent,
RulesComponent,
ContactInfoComponent,
Page404Component,
UserProfileComponent,
NotificationsComponent,
GeneralComponent,
ReportComponent
],
// ...
and app-routing.module.ts
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent
},
{
path: 'userProfile',
component: UserProfileComponent
},
{
path: 'general',
component: GeneralComponent
},
{
path: 'report',
component: ReportComponent
},
{
path: 'notifications',
component: NotificationsComponent
},
{
path: "department/:dep", loadChildren: () => import(`./branches/branches.module`).then(m => m.BranchesModule)},
{
path: 'aboutUs/rules',
component: RulesComponent
},
{
path: 'aboutUs/contactInfo',
component: ContactInfoComponent
},
{
path: 'membership/teacher',
component: TeacherMembershipComponent
},
{
path: 'membership/student',
component: StudentMembershipComponent
},
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{ path: '**', component: Page404Component },
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
the second level is branches that its modules are:
branches.module.ts:
#NgModule({
declarations: [
BranchesComponent,
CoursesListComponent,
TeachersListComponent,
TeacherResumeComponent,
TeacherSelectionFormComponent,
Page404BranchesComponent
],
imports: [
CommonModule,
BranchesRoutingModule,
MaterialDesignModule
]
})
export class BranchesModule { }
and branches-routing.module.ts:
const routes: Routes = [
{ path: '', component: BranchesComponent, children: [
{
path: "coursesList/:branchCourses",
component: CoursesListComponent
},
{
path: "teacherSelection",
component: TeacherSelectionFormComponent
},
{
path: "teacherResume",
component: TeacherResumeComponent
},
{
path: 'coursesList', component: CoursesListComponent
},
{
path: '', redirectTo: 'coursesList', pathMatch: 'full'
},
{
path: '**', component: Page404BranchesComponent
},
]}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
till here, when one of links (departments) in sidenav of app.component.html is clicked, the branches.component is loaded in place of route-outlet of app.component and subscribes the parameters passed from app.component, and lists branches respected to each link.
baranch.component.ts:
export class BranchesComponent implements OnInit {
filteredBranches$!: Observable<Branch[]>;
filteredBranches!: Branch[];
constructor(private route: ActivatedRoute, private branchesService: BranchesService) {
}
activeTab: string=''
ngOnInit(): void {
this.route.paramMap.pipe(
switchMap((params: Params) => {return this.branchesService.getDepBranches(params['get']('dep')) })
).subscribe((branches) => {this.filteredBranches = branches; this.activeTab=this.filteredBranches[0].name});
}
}
and branch.component.html:
<nav mat-tab-nav-bar>
<a mat-tab-link *ngFor="let br of filteredBranches"
[routerLink]="['coursesList', br.code]"
routerLinkActive="activeLink"
(click)="activeTab = br.name"
[active]="activeTab == br.name"> {{ br.name }} </a>
</nav>
<router-outlet></router-outlet>
but, although links of branches are listed in template of branches.component, no courses respect to each branches are shown by coursesList.component which placed in router-outlet of branches.component, because it does not received any route parameter from branch.component, until one of branch link is clicked.
I expect that upon branches links are shown at the same time branches.component is loaded, bellow of them, the courses of the first branch are listed by coursesList.component placed in router-outlet of branches.component.
Whereas no one of branch links is clicked and no parameter passed to coursesList.component, nothing is shown. Therefore, is there a solution to active the first branch link as defualt and pass its courses parameters to coursesList component upon branches.component is loaded? Best regards.
I was building a new angular (v6.0.1) application and wanted to start wiring it up to handle data through a service. I created a new provider as below:
#Injectable({
providedIn: 'root',
})
export class NewsRepositoryProvider {
constructor(private firebase: AngularFireDatabase) {
}
///Gets a news article starting at a certain index and then so many forward
public getPagedNews(start: number, count: number): AngularFireList<any> {
return this.firebase.list('/News/');
}
}
Wanting to make certain this stub worked before I really dived into it, I wired it up and added it to a component constructor:
AppModule:
#NgModule({
declarations: [
AppComponent,
NavMenuComponent,
NewsComponent,
HomeComponent,
ContactComponent,
ProductsComponent,
ApplicationsComponent,
NewsRepositoryProvider,
],
imports: [
CommonModule,
HttpModule,
FormsModule,
RouterModule.forRoot([
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'applications', component: ApplicationsComponent },
{ path: 'contact', component: ContactComponent },
{ path: 'news', component: NewsComponent },
{ path: 'products', component: ProductsComponent },
{ path: '**', redirectTo: 'home' }
]),
AngularFireModule.initializeApp(FIREBASE_CONFIG),
AngularFireAuthModule,
AngularFireDatabaseModule,
],
})
export class AppModuleShared {
}
Component:
constructor(private newsRepo: NewsRepositoryProvider) {
console.log(newsRepo.getPagedNews(0, 10));
}
I run webpack and then launch the page. To my surprise I get the following error:
An unhandled exception occurred while processing the request.
NodeInvocationException: StaticInjectorError(e)[LocationStrategy -> PlatformLocation]:
StaticInjectorError(Platform: core)[LocationStrategy -> PlatformLocation -> InjectionToken DocumentToken]:
Right-hand side of 'instanceof' is not an object
TypeError: StaticInjectorError(e)[LocationStrategy -> PlatformLocation]:
StaticInjectorError(Platform: core)[LocationStrategy -> PlatformLocation -> InjectionToken DocumentToken]:
Right-hand side of 'instanceof' is not an object
at bt (\ClientApp\dist\main-server.js:109:67471)
I've been pouring over StackOverflow questions, trying to determine what could be the root cause of this error. Anyone familiar with the error? Did I do something wrong in setting up the service?
Angular version 6 comes with new way to inject your service for the tree shaking feature so you can use the old one with is add it to the provider array inside your module like this:
providers: [
NewsRepositoryProvider
]
Or inside the service class like this:
#Injectable({
providedIn: 'root',
})
So you should use one of them and i suggest using the way inside your service.
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).
I was trying to navigate from a parent component (Core) using an url dynamically emitted from a child component (Menubar).
The problem is that the navigation is cancelled without any reason.
To find out if the problem came from the parent component, I implemented a button in the parent component navigating to a static url, and it worked!
Core template:
<app-menubar (onNavigation)="onMenubarNavigation($event)"></app-menubar>
<button type="button" (click)="navigate()">Navigate</button>
<router-outlet><router-outlet>
Core component:
onMenubarNavigation(urlSegments: string[]): void {
this.router.navigate(urlSegments);
}
navigate(): void {
let segments: string[];
segments = ['index', 'messages'];
this.router.navigate(segments);
}
Menubar template:
<a (click)="changeRoute(element.module.route)">
// element.module route is the string: "/messages"
Menubar component:
#Output() onNavigation = new EventEmitter<string[]>();
changeRoute(url: string): void {
let urlSegments: string[];
urlSegments = url.split('/');
urlSegments[0] = 'index';
this.onNavigation.emit(urlSegments);
}
App routing module:
const routes: Routes = [
{ path: 'login', loadChildren: '.\/auth\/auth.module#AuthModule' },
{ path: 'logout', loadChildren: '.\/auth\/auth.module#AuthModule' },
{ path: '', loadChildren: './theme/core/app.core.module#AppCoreModule', pathMatch: 'full' },
];
#NgModule({
imports: [RouterModule.forRoot(routes, { enableTracing: true })],
exports: [RouterModule]
})
export class AppRoutingModule { }
Core routing module:
const coreRoutes: Routes = [
{
path: '',
component: AppCoreComponent,
canActivate: [AuthGuard],
children: [
{
path: 'home',
loadChildren: '..\/home\/app.home.module#AppHomeModule'
},
{
path: 'index',
loadChildren: '..\/index\/app.index.module#AppIndexModule'
},
{
path: '',
redirectTo: 'index',
pathMatch: 'full'
}
]
}
];
#NgModule({
imports: [
RouterModule.forChild(coreRoutes)
],
exports: [
RouterModule
]
})
export class AppCoreRoutingModule {}
The angular routing debug shows that both urls are the same during navigation, using the one emitted by the child component or the static one, but when I navigate using the one emitted, the navigation is cancelled and I have no idea why...
Has someone ever encoutered this kind of trouble with the angular router?