2

I have a router connecting several components. Each component can modify the route so that its state can be preserved (copy paste to someone etc.).

Example :

  1. /route/mycomp
  2. play with some field
  3. route becomes /route/mycomp;field=value
  4. click on /route/othercomp, route adapts
  5. click on /route/mycomp
  6. route becomes route/mycomp

I would like it to remain /route/mycomp;field=value instead, since the component itself did not change.

What I tried :

  • changing my RouteReuseStrategy implementation
  • saving url in each component after each filter action
  • changing the DOM

Any ideas ?

Angular 2.3.1.

Maciej Treder
  • 11,866
  • 5
  • 51
  • 74
spin
  • 31
  • 3

2 Answers2

1

You may use 'skipLocationChange'

<a [routerLink]='xxx' skipLocationChange>next</a>

or

router.navigateByUrl('xxx', {skipLocationChange:true}

Reference: https://angular.io/docs/ts/latest/api/router/index/NavigationExtras-interface.html

neuropaddy
  • 47
  • 1
  • 7
  • This one prevents step 4. I eventually found a way by changing RouteReuseStrategy. See main answer. – spin Jun 06 '17 at 07:56
1

This lecture helped :

How to implement RouteReuseStrategy shouldDetach for specific routes in Angular 2

import { RouteReuseStrategy } from '@angular/router'
import { DetachedRouteHandle } from '@angular/router'
import { ActivatedRouteSnapshot } from '@angular/router'

/**
 * Basic implementation comes from @manfredsteyer.
 * We extended it to add functionality described in current issue.
 */
export class CustomReuseStrategy implements RouteReuseStrategy {

  tab: string = null
  handlers: {[key: string]: any/*DetachedRouteHandle*/} = {}

  /// Should detach and not destroy: true (always)
  shouldDetach(route: ActivatedRouteSnapshot): boolean {

    return true

  }

  /// If detached, store
  store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {

    this.handlers[route.routeConfig.path] = {
      handle: handle,
      params: route.params
    }

  }

  /// Should reuse existing component: if avalaible
  shouldAttach(route: ActivatedRouteSnapshot): boolean {

    // Avoid multiple calls
    this.tab = route.routeConfig.path // current tab

    // the double exclamation mark (!!) casts to actual boolean
    return !!route.routeConfig && !!this.handlers[route.routeConfig.path]

  }

  /// Should we retrieve component and parameters
  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {

    if (!route.routeConfig || !this.handlers[route.routeConfig.path])
      return null

    let handler = this.handlers[route.routeConfig.path]
    let sentParameters = route.url.slice(-1)[0].parameters
    let parameters = null

    // Send back params (only if current tab, last retrieve call)
    if (this.tab === route.routeConfig.path) {
      // Which parameters to send to the retrieved component ?

      // If you send parameters from one panel to another
      // (like clicking on a button to access a related object in another panel),
      // then use them
      if (Object.keys(sentParameters).length)
        parameters = sentParameters
      // if you don't, use the old ones (cf. **Expected behavior**)
      else
        parameters = handler.params

      // urlParse() is in each panel component (inheritance is your friend)
      // and can do some specific parameters name and/or value parsing
      // before injecting them into said component
      handler.handle.componentRef.instance.urlParse(parameters)
    }

    return handler.handle

  }

  // I'm not too sure about this part
  /// Should we load/retrieve other component: if path is different
  //  @todo /!\ if routeConfig is null, say "yes"
  shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {

    // @todo: strange case with null/null values
    return future.routeConfig === curr.routeConfig

  }

}

(Copy paste of github.)

spin
  • 31
  • 3