Reputation: 1668
I'm new to Angular 2. I've got a component and a routing module. Basically, I'm trying to follow the Angular routing tutorial). It almost works (well, the content is displayed as intended). The problem is that once I use an URL (say, manually enter http://localhost:4200/items/1, for the sake of simplicity), it rewrites the URL to http://localhost:4200 before I can say "Jack Robinson", while the page itself is displayed correctly. I would prefer a "normal" behavior (i.e. no URL changes, browser's Back button takes me to the previous page, etc.).
What am I missing?
My component in question:
import { Component } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import 'rxjs/add/operator/switchMap';
import { ItemService } from './item.service';
import { Item } from './item';
@Component({
selector: 'item-details',
templateUrl: './item-detail.component.html',
})
export class ItemDetails {
item : Item;
constructor(
private route: ActivatedRoute,
private router: Router,
private service: ItemService,
) {}
ngOnInit() : void {
this.route.params
.switchMap((params : Params ) => this.service.getItem(+params['id']))
.subscribe((item : Item) => this.item = item);
}
}
The routing module for "items":
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ItemsComponent } from './items.component';
import { ItemDetails } from './item-detail.component';
const itemRoutes: Routes = [
{ path: 'items', component: ItemsComponent },
{ path: 'items/:id', component: ItemDetails },
];
@NgModule({
imports: [RouterModule.forChild(itemRoutes)],
exports: [RouterModule]
})
export class ItemsRoutingModule{}
The top routing module:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Http404 } from './Http-404';
const routes: Routes = [
{ path: '', redirectTo: 'items', pathMatch: 'full'},
{ path: '**', component: Http404 },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule{}
Error messages from console (probably irrelevant, as the instance of Item gets rendered correctly):
ng:///ItemsModule/ItemDetails.ngfactory.js:24 ERROR TypeError: Cannot read property 'descr' of undefined
at Object.eval [as updateRenderer] (ng:///ItemsModule/ItemDetails.ngfactory.js:100)
at Object.debugUpdateRenderer [as updateRenderer] (vendor.bundle.js:13619)
at checkAndUpdateView (vendor.bundle.js:12924)
at callViewAction (vendor.bundle.js:13282)
at execComponentViewsAction (vendor.bundle.js:13214)
at checkAndUpdateView (vendor.bundle.js:12925)
at callViewAction (vendor.bundle.js:13282)
at execEmbeddedViewsAction (vendor.bundle.js:13240)
at checkAndUpdateView (vendor.bundle.js:12920)
at callViewAction (vendor.bundle.js:13282)
I hope this is all the code relevant to the problem. Let me know, if not. And thanks in advance.
EDIT:
It turns out, the error messages are relevant to the issue. By replacing my template with a static dummy, I got everything working. And I'm puzzled even more.
Upvotes: 2
Views: 2273
Reputation: 1668
OK, solved it.
The main lesson learned: if anything else throws exceptions in your Angular 2 app, even temporarily, it can break the routing part irreparably.
The issue was not related to routing per se. The culprit was using an asynchronously obtained (via REST API) object in the component's template without checking for the object existence. As the object was not retrieved from an external REST service instantaneously, the error messages about undefined objects were emitted several times until the object was obtained and the component was successfully rendered. But this was enough to break the routing!
So, the solution was to add an **ngIf conditional for the object into component's template:
<table *ngIf="item">
<tr>
<td>
Item description
</td>
<td>
{{item.descr}}
</td>
...
As soon as the error messages were gone, the routing also behaved as expected.
@MichaelPalmer, thank you for pointing me in right direction!
Upvotes: 1