Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 router.navigate reloads app

I have the following routes defined in my app ...

app.components.ts
@RouteConfig([
  {path:'/employees/...', name:'Employees', component:EmployeeComponent},
  ...

employee.component.ts
@RouteConfig([
  {path:'/', name:'EmployeeList', component:EmployeeListComponent, useAsDefault: true},
  {path:'/:id', name:'EmployeeDetail', component:EmployeeDetailComponent}
])

When I route from the EmployeeDetailComponent template ...

<button class="btn btn-default" [routerLink]="['EmployeeList']">Close</button>

the app routes to the employee listing page as expected.

However, when I route using router.navigate ...

// template
<button class="btn btn-default" (click)="save()">Save</button>

// EmployeeDetailComponent
saveEmployee() {
  this._employeeServer.updateEmployee(this.employee);
  this._router.navigate(['EmployeeList']);
}

the app routes the the employee listing (as expected) and then, a few moments later, the app reloads entirely (not as expected).

Any idea why router.navigate is behaving differently than routerLink? What am I missing?

like image 818
Todd Breyman Avatar asked Mar 25 '16 20:03

Todd Breyman


Video Answer


3 Answers

<button> within <form> may be trying to submit. Try adding <button type="button"> to prevent the from submitting when clicking the button.

like image 123
Marc A Avatar answered Oct 24 '22 04:10

Marc A


You could use this directive:

@Directive({
  selector: `click-stop-propagation`
  events: 'stopClick($event)'
})
class ClickStopPropagation {
  stopClick(event:Event) {
    event.preventDefault();
    event.stopPropagation();
  }
}

and apply it this way:

<button class="btn btn-default"
    (click)="save()" click-stop-propagation>Save</button>

Another solution would be to pass the event to the save method:

<button class="btn btn-default"
    (click)="save($event)" click-stop-propagation>Save</button>

and use it to stop the event propagation:

save(event) {
  this._employeeServer.updateEmployee(this.employee);
  this._router.navigate(['EmployeeList']);
  event.preventDefault();
  event.stopPropagation();
}
like image 7
Thierry Templier Avatar answered Oct 24 '22 05:10

Thierry Templier


While Thierry's answer with cancelling the event propagation worked for me, I found another solution;

Try wrapping the navigation in a timeout (of any duration)

...
setTimeout(() => {
    this._router.navigate(['EmployeeList']);
}, 0);
...

Whether or not you find this neater than including a click event is up for debate. For me, I wanted to delay the navigation to wait for an animation anyway, and this way saved me from including an otherwise redundant click event.

like image 1
Squimon Avatar answered Oct 24 '22 04:10

Squimon