3

I want to change the url without reloading the page. I use the location service like:

this.location.replaceState(`mynewurl`); 

When i navigate back, the history is not good. I found the html5 pushState solution.

i ask if there is not a service like Location that handles pushState on angular

5
  • 1
    Check if Location is what you're looking for. BTW, if you want to navigate without reloading, why not use Router? Commented Nov 23, 2018 at 18:31
  • I don't know how to do that ??? Commented Nov 23, 2018 at 18:38
  • What exactly are you trying to achieve here? And also, what exactly do you mean by When i navigate back, the history is not good? Commented Nov 23, 2018 at 18:39
  • I have a route videos and I want when I click on a video, the id of the video is displayed on the url like videos/id without reloading page. I use that id to show an overlay and display the good video Commented Nov 23, 2018 at 18:43
  • I've added an answer. Check it to see if it helps. Commented Nov 23, 2018 at 19:12

1 Answer 1

7

You can follow these steps to achieve it:

  1. import { Routes, RouterModule } from '@angular/router';
  2. Create a routes config:

const routes: Routes = [ { path: '', redirectTo: '/videos', pathMatch: 'full' }, { path: 'videos', component: VideosComponent, children: [ { path: ':id', component: VideoComponent }, { path: '**', component: PlaceholderComponent } ] }, ]; 
  1. Add RouterModule.forRoot(routes) to the imports array of your @NgModule:

@NgModule({ imports: [..., RouterModule.forRoot(routes), ...], ... }) export class AppModule { } 
  1. Add a router-outlet tag to your app.component.html along with an anchor tag to videos route:

<a routerLink="/videos"> Videos </a> <router-outlet></router-outlet> 
  1. In videos.component.html create another router-outlet tag with links to videos:

... <div> <a routerLink="./1">Video 1</a> | <a routerLink="./2">Video 2</a> | <a routerLink="./3">Video 3</a> | <a routerLink="./4">Video 4</a> | <a routerLink="./5">Video 5</a> | </div> <br> <router-outlet></router-outlet> 
  1. You can now get the Video Id in the video component using ActivatedRoute. Use it to display the appropriate video:

import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-video', templateUrl: './video.component.html', styleUrls: ['./video.component.css'] }) export class VideoComponent implements OnInit { videoId; constructor(private activatedRoute: ActivatedRoute) { } ngOnInit() { this.activatedRoute.params.subscribe(params => this.videoId = params['id']); } } 

Here's a Sample StackBlitz for your ref.

UPDATE:

If you don't want to load all the videos, then don't make :id route as a child route to videos. Make this change to your routes config:

const routes: Routes = [ { path: 'videos', component: VideosComponent }, { path: 'videos/:id', component: VideoComponent }, { path: '', redirectTo: '/videos', pathMatch: 'full' } ]; 

And get rid of the additional router-outlet from the VideosComponent. That should be as per the way you want it. I've updated the Sample StackBlitz as well.

UPDATE 2

If you want to display some sort of a modal, then you can use ngx-bootstrap. And then in the video component's ngOnInit open the modal. When the user clicks to close the modal, just navigate back to /videos route.

import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { BsModalService } from 'ngx-bootstrap/modal'; import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service'; import { LocationListenerService } from '../location-listener.service'; @Component({ selector: 'app-video', templateUrl: './video.component.html', styleUrls: ['./video.component.css'] }) export class VideoComponent implements OnInit { videoId; modalRef: BsModalRef; @ViewChild('template') template: TemplateRef<any>; constructor( private activatedRoute: ActivatedRoute, private modalService: BsModalService, private router: Router ) { } ngOnInit() { this.activatedRoute.params.subscribe(params => this.videoId = params['id']); if(!this.modalRef) { this.openModal(this.template); } } openModal(template: TemplateRef<any>) { this.modalRef = this.modalService.show(template); } closeModal() { this.modalRef.hide(); this.router.navigate(['/videos']); } } 

And in your template:

<ng-template #template> <div class="modal-header"> <h4 class="modal-title pull-left">Modal</h4> <button type="button" class="close pull-right" aria-label="Close" (click)="closeModal()"> <span aria-hidden="true">&times;</span> </button> </div> <div class="modal-body"> <p> Playing Video {{ videoId }} </p> </div> </ng-template> 

This should do the job for you. I've re-edited the Sample StackBlitz. Just have a look.

PS: It won't navigate back to /videos on overlay click but the modal will close. That's just one case which you can take care of on your own. Rest all I've explained in the answer. Hope this helps.

UPDATE 3:

For showing the videos in the background, you'll have to again make the ':id' path, a child of the videos path. But then that would again require you to get all the videos to show upfront which is a condition that you wanted to avoid.

I've anyway made an update to the StackBlitz considering what you recently asked me to achieve.

Sign up to request clarification or add additional context in comments.

6 Comments

thanks you but it's a good approch. but i navigate directly to /videos/id. I'll have to load all the videos and that's what I do not want to do
exactly keeping the same url
I want if the user is on the videos page and clicks on a video; I open an overlay to display the video by changing the url like /videos/id and if it does not, if it directly videos/id open another page
would there not be a way to keep the videos visible behind the modal ?
I've updated my answer yet again. What you're looking for should be in Update 3. But that conflicts with your need to not have to fetch all the videos in case the user just lands on the videos/id route.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.