christopherthielen / ui-router-extras

THIS PROJECT IS NO LONGER MAINTAINED -- Extras for UI-Router for AngularJS. Sticky States (a.k.a. parallel states), Deep State Redirect (for tab-like navigation), Future States (async state definition)
http://christopherthielen.github.io/ui-router-extras/
MIT License
917 stars 211 forks source link

Sticky states w/ typed parameters #328

Closed kasperlewau closed 8 years ago

kasperlewau commented 8 years ago

Hiya! I recently posted an issue at ui-router (https://github.com/angular-ui/ui-router/issues/2832) and having played around with the suggested solution I've managed to spawn quite a few errors, unfortunately I haven't come to any conclusion(s).

First, I need to switch around the code in encode and decode in the [supplied answer]() for the code to compute.

$urlMatcherFactoryProvider.type('objid', {
  encode: (o) => o,
  decode: (o) => o.id,
  is: (o) => typeof o === 'object',
  equals: (a, b) => a.id === b.id
});

As can be seen in this jsFiddle, it appears to work just fine™!


However, this will not work if I add sticky: true to the parameterized state.

If sticky: true is added to the state with a parameterized URL, I can enter it once but on reactivation an error will be thrown.

err

jsFiddle (broken)


Now, if I pass some parameters when going to the state:

const feed = { id: 'feed-3804yuhnsdf-234u80' };
const item { id: 'item-29u3804hueonjsdm' };
const params = { feed, item };
$state.go('foo', params);

The onEnter function is called with an odd looking set of params:

onEnter

So it would seem that the encode/decode functionality needs some love at this point (i.e. going back to something that looks a lot more like what @christopherthielen suggested in the above linked ui-router issue).

$urlMatcherFactoryProvider.type('objid', {
  encode: (o) => '' + o.id,
  decode: (str) => str,
  is: (o) => typeof o === 'object',
  equals: (a, b) => a.id === b.id
});

jsFiddle (final)

At this point, it seems to be fine but:

  1. You cannot transition from foo(with params) -> foo(without params). I suppose this is just the default behaviour.
  2. You cannot transition from home -> foo(with params) -> home -> foo(without params). This will throw the following:

err


I ended up with something like this in the very end:

$urlMatcherFactoryProvider.type('objid', {
  encode: (o) => {
     return '' + (o ? o.id : '');
  },
  decode: (str) => {
    return { id: '' + (str.id || str) };
  },
  is: (o) => typeof o === 'object',
  equals: (a,b) => {
    a = a || {};
    b = b || {};

    return a.id === b.id;
  }
});

jsFiddle

With the added guards in equals, encode and decode I can successfully transition between sticky states with typed parameters & default values.

It does feel as if this can be cleaned up vastly, and the errors are slightly worrying to me. It's probably the case of me not groking typed parameters correctly - but the majority of the issues experienced occured as I added sticky: true to my state definition.

I suppose my question is this: Are there any known gotchas with sticky states and typed parameters?

christopherthielen commented 8 years ago

I suppose my question is this: Are there any known gotchas with sticky states and typed parameters?

As of version 0.1.0, sticky states are supposed to understand parameters, including typed parameters: https://github.com/christopherthielen/ui-router-extras/blob/master/src/stickyProvider.js#L107-L108

See this issue: https://github.com/christopherthielen/ui-router-extras/issues/239

christopherthielen commented 8 years ago

You cannot transition from foo(with params) -> foo(without params). I suppose this is just the default behaviour.

Try using <a ui-sref="tostate({})" ui-sref-opts="{ inherit: false }">. You may be seeing the default inherit: true behavior, where a transition inherits the previous parameter values.

You cannot transition from home -> foo(with params) -> home -> foo(without params). This will throw the following:

In your .equals method, you are responsible for checking for nulls, undefined, etc, so I think your last version of .equals is fine.