Refer to current state from ui-sref (e.g. for setting url parameters). #1031

Closed
olegskl opened this Issue Apr 17, 2014 · 37 comments

Projects

None yet
@olegskl
olegskl commented Apr 17, 2014

The documentation explicitly states "You can also use relative state paths within ui-sref, just like the relative paths passed to $state.go()." However, even though we are able to refer to the current state with $state.go('.', {foo: 'bar'}) it doesn't seem to work when using ui-sref directive. I naively tried ui-sref=".({foo:'bar'})" which failed.

Of course it is possible to wire up ng-click and $state.go, but that leaves us with href-less anchors, which is not very useful from the user perspective.

I've ventured a related question on stackoverflow in case somebody had figured it out already. But it appears not to be the case.

Does this functionality exist already (maybe I just missed/misused it)? If not, should it be implemented?

@timkindberg
Contributor

I'll be honest, we never expected the use of just a single dot (.). I'm pretty sure you can just do this though now ui-sref="{foo:'bar'}".

@olegskl
olegskl commented Apr 18, 2014

I tried <a ui-sref="{foo:'bar'}">foobar</a> too and it gave me:

Error: Could not resolve '{foo:'bar'}' from state ''

Setting up a breakpoint inside of $state.go reveals that it is called like so:

$state.go("{foo:'bar'}", null, ...)

And then the error is thrown inside $state.transitionTo, on L785. I'm using v0.2.10.

@timkindberg
Contributor

Hmm here's the commit that added that feature.

71cad3d

@olegskl
olegskl commented Apr 18, 2014

Indeed, it's not in the 0.2.10 yet. I have cloned the master branch, built it and took the files from the "build" folder. And now <a ui-sref="{foo:'bar'}">foobar</a> works fine when I put it inside a ui-view partial, though it doesn't get updated when the current state changes (I guess I was hoping for too many things at once...).

However, if put it outside of ui-view (but still inside of ng-app of course), no matter the url, on page load I'm getting:

Error: Invalid state ref '({foo:'bar'})'

So, when the directive is outside of a ui-view, the $state.current.name in $StateRefDirective's link function is always an empty string when activating a state by navigating to a url. Thus, no href attribute is created when page is rendered.

It could be intended/unavoidable behaviour though, I'm not sure.

@timkindberg
Contributor

Thanks for looking into it. Hopefully we'll take a look soon.

@czebe
czebe commented May 27, 2014

We're also missing this feature. Currently there's no clean way to link back to the current state without query parameters (remove parameters and trigger state change).

@lunow
lunow commented Aug 21, 2014

+1

@daviddeutsch

I can confirm that this works in 0.2.11 - no more error. However, it seems like the page is still reloaded.

@thomastuts

I just tried this out and while it works perfectly when you load the page, if I change a state (e.g. from 'dashboard' to 'explore'), it still tries to redirect the user to dashboard/5 instead of explore/5 when I hover over a link. It's like the ui-sref doesn't update the state it needs to redirect to (i.e. the current state). Any ideas on why this is?

@albertpeiro

+1 on this. Pretty pressing for handling user-friendly async pagination.

@demisx
demisx commented Mar 22, 2015

+1

@bennewton999

+1

@zschiffelbein

+1 using ui-sref="{foo: 'bar'}" renders the href tag on the first state and does not continue to update on state changes.

edit: Spoke too soon. I got this to work. Remove the ui-sref tag and add ng-click="$state.go('.', {foo: 'bar'})". Hope this helps.

@nateabele
Member

Okay, so sounds like maybe the $watch() is wrong. If somebody can post me up a quick Plunkr I'll take a look at it.

@zschiffelbein

Pretty sloppy, but it should give you an idea. The expected outcome is for it to stay on either the color or size route when you click on a different item. http://plnkr.co/edit/fARlus6UmokOsdRxbaoS

@dferrin
dferrin commented Apr 26, 2015

I just updated the plunk with AngularJS 1.3.15 and ui-router 0.3.14 and the href tag still does not get updated on state change. http://plnkr.co/edit/8jZCbEVuoO4srwU8fIY5?p=preview

@nateabele
Member

Okay, I see the issue. Should be able to patch it later today.

@nateabele nateabele self-assigned this Apr 27, 2015
@zivc
zivc commented May 1, 2015

@nateabele any luck?

@darynmitchell

Confirm I am able to switch between items in my current state by changing one param value using

<a ui-sref="{ itemId: myItem.id }">

angular 1.3.14, angular-ui-router 0.2.13

@ruleb
ruleb commented Jun 15, 2015

This only works the first time.

<a ui-sref="{ itemId: myItem.id }">

On later changes, the itemId is correct, but the suffix part of the pageload URL is used.

Angular 1.3.15, angular-ui-router 0.2.15.

@spongessuck

This seems to work for me:

ui-sref='.({ id: theID })'
@darynmitchell

@ruleb I later found what you said: I was mistaken, it only worked the first time, but not on later changes. Ended up with a workaround involving marking some states as needing reload using the data object (data: { reload: true }), and then a $on('$stateChangeStart' handler to see that and perform the reload.

Seems to be working as needed (~2 months use) but feels like a fragile workaround.

@shprota
shprota commented Oct 1, 2015

I would like to submit a possible solution for this issue.
The proposed method is to treat the dot placeholder as current state name i.e.:

ui-sref=".({locale: langCode})"

Change details:

In the ui-sref directive code:

  var update = function(val) {
    if (val) def.params = angular.copy(val);

    // If specified state is the "." placeholder, substitute it for the current state name:
    def.href = $state.href(ref.state === '.' ? $state.current.name : ref.state, def.params, def.options);

    if (active) active.$$addStateInfo(ref.state, def.params);
    if (def.href !== null) attrs.$set(type.attr, def.href);
  };

And then watch for the state change to update the href when current state changes:

  if (ref.state === '.') {
    scope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) {
      if (fromState.name !== toState.name) {
        update();
      }
    });
  }
@romain10009

+1 for handling "."

@timricker

+1 for an elegant notation such as "." to refer to the current state.

Has there been any further progress on this?

@burzum
burzum commented Jan 11, 2016

+1 for the dot proposal!

@netstyler

+1 for handling "."

@matt-hernandez

+1 for the dot proposal!

@gztomas
gztomas commented Jan 15, 2016

+1

@vincentngthu

+1

@mrova
mrova commented Feb 9, 2016

+1

@nateabele nateabele added the PR-Wanted label Feb 9, 2016
@nateabele
Member

Anyone who would like to submit a PR to implement this is welcome to do so.

@shprota
shprota commented Feb 10, 2016

Submitted my solution

@mrova
mrova commented Feb 10, 2016

@shprota works for me, thanks!

@Maximaximum

It would be great if you could merge @shprota's PR.

@christopherthielen christopherthielen added this to the 1.0.0-beta.4 milestone Nov 8, 2016
@christopherthielen
Contributor
christopherthielen commented Nov 8, 2016 edited

I've done some analysis on this. We can't use "." to mean "the current state" because it already has specific meaning, and it is context sensitive. A relative link is relative to its context (the state that the ui-sref was created in). This means that ui-sref="." (defined in the state called home) always links to template's state (home), even if a substate (home.foo) is the current active state.

"." cannot refer to the currently active state, and we already have syntax for parameter-only ui-srefs, but it is broken in some cases. I am fixing the existing parameter-only ui-sref syntax so it updates when the state changes. i.e., ui-sref="{ id: 345 }"


Here's an example which has two states: home and home.foo. There are both styles of ui-sref links, and their equivalent ui-state links. Note the difference in behavior (when the current state is home.foo) between links with a "." links without one.

http://plnkr.co/edit/JzuxiVezaAaW697JYE8o?p=preview


here is @zschiffelbein plunker with the new changes: http://plnkr.co/edit/Vs8FcVn1bQO60vo8HHNl?p=preview

@christopherthielen christopherthielen added a commit that referenced this issue Nov 8, 2016
@christopherthielen christopherthielen test(ui-sref): Implement failing test for #1031
- ui-sref with only parameter values should always refer to the current state (not context sensitive)
98a5386
@christopherthielen christopherthielen added a commit that closed this issue Nov 8, 2016
@christopherthielen christopherthielen fix(ui-sref): Update params-only sref when state changes
- ui-sref="{ id: 123 }" should always link to the current state with the param values

Closes #1031
Supersedes and Closes #2541
3c1bd0e
@christopherthielen christopherthielen added a commit that referenced this issue Nov 8, 2016
@christopherthielen christopherthielen fix(ui-state): Process ui-state links relative to where they are created
refactor(ui-sref): consolidate ui-sref/state target state processing

Related to #1031
Closes #3139
cae4dc4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment