17

I have angular 5 basic beginner level app there are just 5 components

my routing and links look like this

//copied from app.module.ts
const appRoutes:Routes = [
  {path:'',component:HomeComponent},
  {path:'items/:cat',component:ItemsComponent},
  {path:'itemdetail/:id',component:ItemdetailComponent},
  {path:'settings',component:SettingsComponent},
];

//copied from navbar.component.html
<ul>
      <li><a [routerLink]="['/']">Home</a></li>
      <li><a [routerLink]="['/items/8']">Rashion</a></li>
      <li><a [routerLink]="['/items/2']">Vegitables</a></li>
      <li><a [routerLink]="['/items/3']">Fruits</a></li>
      <li><a [routerLink]="['/items/7']">Other</a></li>
      <li><a [routerLink]="['/items/5']">Sweets</a></li>
      <li><a [routerLink]="['/settings']">Settings</a></li>          
</ul>

//copied from items.component.ts
ngOnInit(){
    this.cat = this.route.snapshot.params['cat'];
    this.itemsSrv.getItems(this.cat)
            .subscribe((data)=>{
                this.items=data;
            });
}

links only work if it is going to different component,
means I can navigate from home page to /items/2
but when I am in items component I can navigate to /items/any-parameter
although from Items i can go to home or settings component.
in short it is now working to navigate to same component even if parameter is different. enter image description here

I noticed one thing, URL is getting changed but page content is same as old page not reloading new url :(

7
  • give detail about your question. I am not getting what you are saying Commented Apr 9, 2018 at 18:00
  • Dont use specific params but optional params like this : [routerLink]=['/items', {param1:'test'}] your route will look like this : /items;param1=test . You only need to specify 'items' without params on your routing Commented Apr 9, 2018 at 18:11
  • @Gilsdav i tried your method, it is saying: Cannot match any routes. URL Segment: 'items/2' Commented Apr 9, 2018 at 18:29
  • With better Reading of your question, my answer was not what you need. Is the page the same as before you changed the parameter ? How do you take the id ? I think that's possible that the component is not recreated but only give you an event that params changed. Do you subscribe params ? Commented Apr 9, 2018 at 18:41
  • items components calling web service with dynamic parameter (1,2...9) which returns list of fruits, sweets, vegitables etc on the basis those params Commented Apr 9, 2018 at 18:46

9 Answers 9

22

So, the best way is using subscribe for route:

userSubscription: Subscription;
...
ngOnInit() {
   this.userSubscription = this.route.params.subscribe(
            (params: Params) => {
                 //------ some code -----
   })
}

After that, you must to unsubscribe:

ngOnDestroy(): void {
        this.userSubscription.unsubscribe()
}
Sign up to request clarification or add additional context in comments.

1 Comment

You don't need to unsubscribe Observables created by angular (opposed to Observables created by yourself). Angular takes care of that. At least in angular 9 that is the case. I don't know about the earlier versions.
10

I know this is a little late but I just ran into the same issue and found a solution. You are using this.route.snapshot.params to get the id parameter. Per the Angular documentation, only use snapshot when your component instance will never be reused. Snapshot only provides the initial value of the route parameter map and does not get updated when the component is reused. This means if you route to a component by id and then (while displaying that component) try to route to a new instance of the same component with a different id, the initial component will be reused but the data will not update because ngOnInit() is not called a second time.

To fix the issue you must change;

this.cat = this.route.snapshot.params['cat'];

To use this format;

ngOnInit() {
  this.cat$ = this.route.paramMap.pipe(
    switchMap((params: ParamMap) =>
      this.itemsSrv.getItems(params.get('id')))
  );
}

The this.route.paramMap is returned from an Observable which

"implies that the route parameter map can change during the lifetime of this component".

You will probably have to modify other parts of your code to work with the Observable (cat$), but since I can only see part of your code I can't advise on other changes. In the documentation below there is a project file (hero-detail.component.ts) at the end of Milestone 3 showing how this works.

You can read the official documentation here;

Angular2+ Observable paramMap and component reuse

Hope this helps and happy coding!

Comments

4

I think this is the best solution

constructor(route:ActivatedRoute) {
 route.params.subscribe(val => {
 // put the code from `ngOnInit` here
  });
}

The router only destroys and recreates the component when it navigates to a different route. When only route params or query params are updated but the route is the same, the component won't be destroyed and recreated. Happy to hear if helped.

Comments

3

When you are navigating to the same component, Angular is not going to re-fire your ngOnInit() method. To get your code working, you will need to work with a version of the route parameters that are an observable and subscribe to changes on that. Make sure you read over the Angular Docs about routing. They have a bunch of helpful information in there.

ngOnInit(){
    this.route.paramMap
        .switchMap(params => this.itemsSrv.getItems(params.get('cat')))
        .subscribe(data => {
            this.items=data;
        });
}

You'll need to make sure that you unsubscribe from this subscription when you navigate away from this component. Here is a discussion on the best practice on how to do it.

Comments

1

I have also face this problem while doing my project the best to get rid of that error is use subscribe for route and than use Ondestroy interface for unsubscribe an event

    ngOnInit{
       this._router.params.subscribe(param =>{
            // write some code
           let cat=this._router.snapshot.paramMap.get('cat');
          });
}

// after that you must unsbscribe

    ngOnDestroy(){
    }

Comments

1
 ngOnInit() {
    this.activeRoute.queryParams.subscribe(queryParams => {
        //Do something here
    });

    //Or

    this.activeRoute.params.subscribe(routeParams => {
        this.loadUserDetail(routeParams.id);
    });
 }

The following code works when we created a route with the parameter to access data from API sometime user click on the same route a second time with a different parameter and our ngOnint does not call our function the second time which we try to call likes this

   ngOnInit() {
        this.loadUserDetail(this.id);
         // OR
        this.loadUserDetail();
     }
loadUserDetail(id){
        return this.http.get(this.apiUrl+'/'+ id).subscribe(
            (res: any) => {
                  this.products = res['data'];
                  this.seoService.updateTitle(this.products[0]['title']);
                  this.seoService.updateOgUrl(this.products[0].keyword);
                
              
   this.seoService.updateDescription(this.products[0].description);
                  console.log(this.products);
              },
            (error:HttpErrorResponse) => {
              console.log('Error in Fetching  Menu');
              this.products = error.error;
              console.log(this.products);
            }
          );
     }

Sorry for Bad English and explanation

1 Comment

Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes.
1

It happens because angular is reusing that component. Just stop the reusing functionality with below code and it'll work fine.

constructor(private router: Router) {
    // this is for routerLink on same component when only queryParameter changes
    this.router.routeReuseStrategy.shouldReuseRoute = () => false;
  }

Comments

1

Version: Angular: 14.1.0

Assume you are redirecting to below component for different URLs with different query parameters. Just setting one property on router should work for you.

@Component({
  selector: 'app-attendance',
  templateUrl: './attendance.component.html',
  styleUrls: ['./attendance.component.css']
})
export class AttendanceComponent implements OnInit {

    constructor(private router: Router) { }

    ngOnInit(): void {

        this.router.onSameUrlNavigation = 'reload';

    }
    
}

Comments

0

If you trying to route to the same Component with different route param. This worked for me.

 getConsingmentwithId(id: number){
    this.router.navigate(['component', id], {relativeTo: this.route.parent});
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.