Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can we pass objects these days with transitionTo ? #983

Closed
Bretto opened this issue Mar 27, 2014 · 24 comments
Closed

Can we pass objects these days with transitionTo ? #983

Bretto opened this issue Mar 27, 2014 · 24 comments
Labels
Milestone

Comments

@Bretto
Copy link

Bretto commented Mar 27, 2014

can we pass objects these days with transitionTo ?

@nateabele
Copy link
Contributor

Not yet, but soon.

@tbassetto
Copy link

Are we talking about passing information when changing state that we do not want to appear in the URL? Any way I can help? :)

@IainCole
Copy link

IainCole commented Apr 4, 2014

I have some code here that does just that if it helps. https://github.com/Webinfinity/ui-router/tree/optional-params

@mfzl
Copy link

mfzl commented Jun 25, 2014

Is there a workaround for this, for the time being? It's a bit confusing what the correct format for params is, in state declarations. On #400 it says issue is tracked on #125 and #125 seems to be closed, so I assumed that it's fixed now, but it's not. Not in 0.2.10 at least.

@lightswitch05
Copy link

@faxal its fixed in master but has not been released yet. It looks like they have it tagged for the 0.4.0 release, but haven't got 0.3.0 released yet.

@itkin
Copy link

itkin commented Oct 31, 2014

+1 this feature would be awsome :-)
@lightswitch05 where do you see that it is tagged on 0.4.0 or resolved on master ?

@lightswitch05
Copy link

@itkin I'm pretty sure I got this from Typed and optional parameters - #1032 which was released in 0.2.11

@itkin
Copy link

itkin commented Nov 3, 2014

@lightswitch05 got it thx !

@christopherthielen
Copy link
Contributor

Yes, this should be working now in 0.2.13.

.state('foo', { 
  url: '/foo/:param1?param2',
  params: { param3: null } // null is the default value
});

$state.go('foo', { param1: 'bar', param2: 'baz', param3: { id: 35, name: 'what' } });
$stateParams in 'foo' is now { param1: 'bar', param2: 'baz', param3: { id: 35, name: 'what' } }
url is /foo/bar?param2=baz.

@kilaka
Copy link

kilaka commented Jun 3, 2015

Tried and worked using transitionTo . Didn't try with go. AngularJS v1.3.6.

@shavo007
Copy link

👍

@filipesilva
Copy link
Contributor

Tried and worked with go, but I'm getting some inconsistent behavior depending of the parameter.

The target state seems to only reloaded if the param is different at a shallow level. Example in this plunker.

In that example, I have an array that is filled with random numbers when you click the link.

If I send that array into state.go directly, the child state will not be reloaded (check console for child loaded messages). But if I slice the array (creating copy of the array reference) then the child state is reloaded.

I would expect the state to be reloaded regardless, since the contents of the parameter changed.

@christopherthielen
Copy link
Contributor

I'm pretty sure we don't do deep comparisons by default. I think we do 'a == b' and since you reuse the same array reference they are '=='. We have support for array-type for url parameters, but I'm not sure how that would work for non URL params ('array: true'). Otherwise, implement your own type with an equals() that deep compares. Come to think of it, you might be able to set the param type to "json" which does deep compare.

@filipesilva
Copy link
Contributor

I can't seem to find the param type 'json' in the documentation, is it a new addition?

@christopherthielen
Copy link
Contributor

Your plunk works with 'json' type: http://plnkr.co/edit/kBmbxyaU8eWVlNKtEHwX?p=preview

Yeah, json parameter type was added here: https://github.com/angular-ui/ui-router/releases/tag/0.2.13 but looks like it never got documented. Check it out: 027f1fc

@christopherthielen
Copy link
Contributor

As a followup, I actually created the "any" type for exactly your scenario. It doesn't encode/decode and uses angular.equals to do a deep compare. Use that instead of 'json' type.

However, I also thought that non-url parameters were automatically declared as "any" types, hrm...

#1562

3bfd75a

@filipesilva
Copy link
Contributor

Indeed types 'json' and 'any' solve my issue on my production website, many thanks!

Going over those commits, it seems the whole 'type' section of params is undocumented here.

Would a PR of mine to document it be welcome, or is this something on the pipeline for later on?

@christopherthielen
Copy link
Contributor

Hold up. I've made a few stupid mistakes while looking at your plunk:

  1. non-url parameters do indeed use the 'any' type by default. Therefore your original plunk was using the 'any' type.

  2. Declaring type: 'any' or type: 'json' is not currently a valid param configuration option. I thought it was valid, and I think we should make it valid in the future. See my note below:

  3. the reason your plunk "works" when I changed it to type: 'json' is that:

  • It actually passed the string literal 'json' to the Type constructor, making a new anonymous type with the default implementation (which, ironically, uses == to test equality)
  • You are always passing params as a a new object literal to state.go(foo, { obj: {array: blah } }), and so toParams == fromParams is always false, since they're different object references

So, now with a fresh perspective, the reason ui-router thinks your parameter has not changed in your original plunk is as follows:

  1. It was indeed using the 'any' type
  2. It was doing a deep compare of the object
  3. You live-updated the from params when you pushed the new value. The from params have a reference to your array.
  4. You create a new object and put a reference to the same array inside it
  5. The to params and from params are equal, according to angular.equals

The answer you're looking for is to create a copy of the array, before sending it to $state.go, I've updated my plunker showing how: http://plnkr.co/edit/kBmbxyaU8eWVlNKtEHwX?p=preview

Note from above:
We should update getType to get the type from the $types registry, if the config.type is a string in this block of code:

    function getType(config, urlType, location) {
      if (config.type && urlType) throw new Error("Param '"+id+"' has two type configurations.");
      if (urlType) return urlType;
      if (!config.type) return (location === "config" ? $types.any : $types.string);
      return config.type instanceof Type ? config.type : new Type(config.type);
    }

@filipesilva
Copy link
Contributor

I think I understand. In fact, that splice you found odd in the plunkr was a bug in my attempt to copy the array via 'slice`!

My real world scenario is slightly more complex: I am live-updating several arrays, which then I put inside of an object and send it as parameters for $state.go. Thus I can either slice all those arrays, or set the type (which will end up being anonymous) on the state params.

@filipesilva
Copy link
Contributor

Regarding your note, I believe this should do the trick:

    function getType(config, urlType, location) {
      if (config.type && urlType) throw new Error("Param '"+id+"' has two type configurations.");
      if (urlType) return urlType;
      if (!config.type) return (location === "config" ? $types.any : $types.string);
      if ((config.type instanceof String || typeof config.type === 'string') 
        && $types[config.type]) return $types[config.type];
      return config.type instanceof Type ? config.type : new Type(config.type);
    }

I need to read up on the tests here on ui-router and try to setup my env to run them, afterwards I can do a PR to implement and test.

@christopherthielen
Copy link
Contributor

My real world scenario is slightly more complex: I am live-updating several arrays, which then I put inside of an object and send it as parameters for $state.go. Thus I can either slice all those arrays, or set the type (which will end up being anonymous) on the state params.

I don't think you want to rely on toParams == fromParams because that will always return false, and your state will always reload.

Can you instead do $state.go("foo", angular.copy(paramsObj))?

@christopherthielen
Copy link
Contributor

npm install && bower install
grunt karma:watch / grunt karma:unit / grunt karma:debug

While developing a test, find the describe block you're interested in and change describe to ddescribe (this will cause jasmine to run only that block).

https://github.com/angular-ui/ui-router/blob/master/test/urlMatcherFactorySpec.js#L483-L591

@nateabele
Copy link
Contributor

I think you mean fdescribe.

@christopherthielen
Copy link
Contributor

I think you mean fdescribe.

0.2.15 is still on an older jasmine version so it uses iit and ddescribe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests