2

I'm not sure if this is the best way to implement this. If you have other opinions please share.

I have to implement a multi inbox system where the user can have multiple emails grouped by different inboxes.

For example: http://localhost/inbox/personal/ will show a list of emails in personal inbox, http://localhost/inbox/business/3 will show a list of emails in business inbox and will highlight email with id: 3

Routes look like this:

const routes: Routes = [
  {
    path: '',
    pathMatch: 'full',
    redirectTo: 'personal' // redirect to personal inbox
  },
  {
    path: ':inbox',
    component: InboxContentComponent, // list of emails in :inbox
    children: [
      {
        path: '',
        component: InboxNoSelectedEmailComponent, // no email selected
      },
      {
        path: ':id',
        component: InboxSelectedEmailComponent, // show selected email content
      }
    ]
  }
];

My problem is with InboxContentComponent . I need to detect when inbox changes and if an email is selected or not

  constructor(private route: ActivatedRoute) {
  }
  ngOnInit() {
    this.route.paramMap.subscribe(inbox => {
      console.log('inbox', inbox);
    });
  }

Events are emitted only when inbox changes and not when email changes. Is there a way to detect when child route parameters changes?

Doing this this.route.firstChild.paramMap.subscribe(); only works if on component initialization the route has a first child. if the route is like this http://localhost/inbox/business/ then this.route.firstChild is null

On solution I could think is to define routes like this

{
    path: ':inbox/:id',
    component: InboxContentComponent
}

and then check in InboxContentComponent if :id is set or not

Any ideas?

Doua Beri
  • 10,612
  • 18
  • 89
  • 138
  • 1
    I think this answer will provide you possible solution idea: https://stackoverflow.com/questions/48807518/how-to-handle-angular-5-recursive-unknown-exact-number-router-parameters/48808565?noredirect=1#comment84654490_48808565 – Oleksandr Poshtaruk Feb 25 '18 at 20:20

1 Answers1

8

To tackle this kind of problem, I would listen to router events and retrieve what I want. Something like this :

import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
import { filter, map, mergeMap, tap } from 'rxjs/operators';

// ...
constructor(
    // ...
    private activatedRoute: ActivatedRoute,
    private router: Router
  ) {
    this.router.events
    .pipe(
      filter((event) => event instanceof NavigationEnd),
      map(() => this.activatedRoute),
      map((route) => {
        while (route.firstChild) route = route.firstChild;
        return route;
      }),
      mergeMap((route) => route.paramMap),
      tap(
        paramMap => console.log('ParamMap', paramMap)
      )
    ).subscribe(
      (paramAsMap) => // Get the params (paramAsMap.params) and use them to highlight or everything that meet your need 
    )
  }

You can adapt this to your need. Params ? Highlight : NoHighlight.

mickdev
  • 2,765
  • 11
  • 15
  • When attempting the above with Angular 10, tslint says: Property 'filter' does not exist on type 'Observable' – Leif Jones Feb 11 '21 at 18:35
  • 1
    Hi mickdev, could you please explain the `while(route.firstChild) route= route.firstChild` part of your answer? I am not sure I get it – Dario Piotrowicz May 25 '21 at 09:04
  • hey @DarioPiotrowicz, did you get it? I am interested in getting it too :p – Iraklis Bekiaris Apr 14 '22 at 11:54
  • Hey @IraklisBekiaris sorry for the late reply, I think I get it, basically if you have multiple child routes (so multiple `router-outlet`s), you may need to "drill down" to the route you are interested in, have a look at this stackblitz I made: https://stackblitz.com/edit/angular-ivy-tudm6k?file=src%2Fapp%2Fhello.component.ts there you can see when you click the link what this whole while-firstChild loop actually does. I hope this helps :) – Dario Piotrowicz Apr 23 '22 at 21:45