I have a problem with Angular 2 routing. When I click on my link to get the team details, it takes the right route and loads the component specified (TeamComponent). But, immediately "gets back" to the previous component (TeamsComponent), which is the teams list.
This is the structure of my project:
/app
|_shared
|_team
|_team.component.css
|_team.component.html
|_team.component.ts
|_team.model.ts
|_team.service.ts
|_team-list
|_team-list.component.css
|_team-list.component.html
|_team-list.component.ts
|_teams
|_teams.component.css
|_teams.component.html
|_teams.component.ts
|_teams.module.ts
|_teams-routing.module.ts
First, I set the routes on teams-routing.module.ts:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TeamsComponent } from './teams.component';
import { TeamComponent } from '../shared/team/team.component';
const teamsRoutes: Routes = [
{
path: 'team/:id',
component: TeamComponent
},{
path: 'teams',
component: TeamsComponent
}
];
@NgModule({
imports: [
RouterModule.forChild(teamsRoutes)
]
})
export class TeamsRoutingModule { }
Load the team list from the teamService on teams.component.ts and send it to team-list on teams.component.html:
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/from';
import { TeamService } from '../shared/team/team.service';
import { Team } from '../shared/team/team.model';
@Component({
selector: 'app-teams',
templateUrl: './teams.component.html',
styleUrls: ['./teams.component.css']
})
export class TeamsComponent implements OnInit {
teamList: Team[] = [];
constructor(private teamService: TeamService) { }
ngOnInit() {
this.teamService.getTeams().subscribe(teams => {
Observable.from(teams).subscribe(team => {
this.teamList.push(team);
});
});
}
}
teams.component.html
<section class="teams">
<app-team-list [teams]="teamList"></app-team-list>
</section>
Then, with my teams list, I set the HTML list on team-list.component.html:
<section *ngFor="let team of teams" class="team_list">
<div class="card" style="width: 20rem;">
<img class="card-img-top" src="/assets/logos/{{team.logo}}" alt="Team Logo">
<div class="card-block">
<h4 class="card-title">{{team.name}}</h4>
<p class="card-text">{{team.location}}</p>
<a routerLink="/team/{{team.id}}" class="btn btn-primary">Team Info</a>
</div>
</div>
</section>
Finally, I get the team info from param "id" and the service in team.component.ts:
import { Component, Input, OnInit } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { Team } from './team.model';
import { TeamService } from "./team.service";
import 'rxjs/add/operator/switchMap';
@Component({
selector: 'app-team',
templateUrl: './team.component.html',
styleUrls: ['./team.component.css']
})
export class TeamComponent implements OnInit {
team: Team = null;
constructor(private teamService: TeamService,
private activatedRoute: ActivatedRoute,
private router: Router
) {}
ngOnInit() {
let teamId: number = this.activatedRoute.snapshot.params['id'];
console.log("Vamos a buscar el equipo");
this.teamService.getTeamById(teamId).subscribe(team => this.team = team);
}
}
It loads the TeamComponent HTML with the team data, but gets back to /teams direction (and doesn't print the team list). I tried to change the routes names (/detail/:id for example) but still doesn't work. Any suggestions? Thanks in advance.
Ok, got it. Your request will be exuted async, so at the creation-time of your component, team is null. I think you have a binding like this in your TeamComponent:
{{ team.name }}
If team is null, name cannot be accessed and it crashes. To be sure the html will be rendered without errors, use the elvis-operator like this:
{{ team?.name }}
This will only access name if team is not null or undefined