-
Notifications
You must be signed in to change notification settings - Fork 3k
feat(uiStateActive): directive to add/remove classes for active state #635
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
Conversation
} | ||
|
||
// Test that we have the correct route params, if any | ||
function matchingParams() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about angular.equals()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, lets try it --- I would have assumed that it would return false of o2
has a key that o1
doesn't, but this appears to be false...
...
seems to work in the plnk, I'll shrink that down a bit
Hey, this is awesome. I'll write up some tests for ya tomorrow morning. Really the only other idea I had for this was the ability for the parent-style usage to respond to multiple |
}; | ||
|
||
$scope.$on('$stateChangeSuccess', update); | ||
$scope.$on('$routeChangeError', function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, last thing, then I'll stop bothering you till tomorrow. 😄 Since ui.router
doesn't broadcast any $route*
events, I'm guessing you meant $stateChangeError
?
Also, since a state change error just rolls back to the current state, I'm pretty sure only intercepting $stateChangeSuccess
is enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
er, yes... that is supposed to be $stateChangeError, hah.
Also, testing with http://jsbin.com/oKOZITa/1/edit it looks like angular.equals might not be a good solution (in case a route has parameters which are not taken into account by the ui-sref)
Hey, I wrote up some tests. Just threw everything in a branch for convenience: https://github.com/angular-ui/ui-router/tree/caitp-issue-19 Feel free to keep working off the branch, or just squash it into your PR. |
Awesome! Was also thinking it could be cool if you could use the directive to set other things other than a class, first one that came to mind was the title attr. Something like: |
It's easy to add later, but let's see if there's a use case for it. We also have filters now, which offer another approach to handling that. |
Indeed
|
Regarding the page title, suppose something like this, completely unrelated to the directive: $stateProvider
.state('app', {
templateUrl: '...',
controller: 'AppCtrl',
abstract: true,
url: '',
title: 'ApplicationName'
})
.state('app.welcome', {
...,
views: {
'main@app': {
title: 'Welcome'
}
}); The $state service could look at the state configuration and say "Okay, I guess I need the title to be I mean a directive might make it a bit more flexible, but it doesn't seem unreasonable to me to be able to do it that way |
Oh, I thought he meant the |
Oh I see, yeah maybe. @nateabele: your caitp-issue-19 branch has a lot of changes (compared with master), do you want to split some of that stuff out into smaller commits? Some of it looks like style fixes and some of it is new utility functions, etc |
Adds a directive to switch a set of classes in a DRY fashion by interacting with neighboring ui-sref directives. The class to be used is an interpolated string, which is not $observed. There is no default, as I do not wish to tie this module to a particular CSS model or framework. A default may be configured in the future with a provider. As usual, multiple classes may be used, as Attributes.$addClass/$removeClass will separate classes on whitespace. CAVEATS: This is only capable of working as a parent of a ui-sref directive, or as a sibling directive on the same element. In the future, there may be a mechanism around this, but for the time being I can't think of what it would look like. USAGE: Sibling directive on same element as ui-sref: <a ui-sref="foo.bar({baz: '123'})" ui-state-active="active" href>123</a> --- OR --- Ancestor directive of ui-sref: <li class="item" ui-state-active="active"> <a ui-sref="foo.bar({baz: '123'})" title="123" href>123</a> </li>
@caitp Yeah, sure. One of 'em is a utility function I copied over from |
it might not be too big of a deal, it looks not too unclean this way |
However, using @attrs.$add/$remove class is likely a better idea than $element, it's supposed to play nicer with ngAnimate + ngClass |
@caitp Yeah I wasn't sure about that one. I changed it because we still test against 1.0.6 (wherein those methods apparently don't exist), but I guess it's time to up the minimum requirements. |
Since it's a bit tied to ui-sref, maybe |
paramKeys aren't needed when using `equalForKeys()` strategy
I agree |
@nateabele what would you prefer to do, merge the existing stuff and rename it before the next release, or something else? |
@caitp Yeah, I'm down with the rename. That way, we leave open the possibility of using |
you've already added support for the release candidate's updated ngAnimate stuff right? |
Renamed to reflect the association with the ui-sref directive.
On a branch, yeah, but I haven't done anything about ensuring those changes are compatible with < 1.2. Obviously the simplest thing would be to drop support for pre-1.2, but I haven't even upgraded my work apps to 1.2 yet. |
feat(uiStateActive): directive to add/remove classes for active state
Awesome. I also wrote something this week regarding #19. It's a slightly different approach to allow you setting a state name yourself if you do not have a "ui-sref" attribute "neighbour". I'll attach it in case someone finds it useful. .directive('uiStateActive', function($state) {
return {
restrict: 'A',
link: function (scope, element, attributes) {
scope.$on('$stateChangeSuccess', function() {
var stateName;
if(typeof attributes.uiSref != 'undefined') {
stateName = attributes.uiSref;
}
if(typeof attributes.uiStateActive != 'undefined' && attributes.uiStateActive) {
stateName = attributes.uiStateActive;
}
if(stateName) {
if($state.includes(stateName)) {
element.addClass('active');
} else {
element.removeClass('active');
}
}
});
}
};
}) I wanted to finish this one first to make it more compatible and configurable. But as this is released, I'll just throw it in. 👍 |
Thanks. Yeah, we'll probably roll with something similar later on. |
Would be nice if it would work with nested states, so that it would keep active class even if we navigate to substates |
@chopachom Yeah, there are plans for that. One thing at a time. |
Or take solutions like mine until then. :)
|
I have fairly high latency on my resolves as they go across the pacific.It is a bit of a UX failure pressing some nav element and waiting with no feedback. I wouldn't mind it if ui-sref-active listened on $stateChangeStart as well as $stateChangeSuccess and put a "loading" class on there while the resolves happen then removes it and adds the "active" class. |
I'm not sure why doing that would need to be specific to this particular directive, but maybe (if it's not too large), we could have a separate directive doing that. It seems like behaviour which is not totally part of the concerns of ui-sref-active. But I guess it all depends on what people think about it |
Fixes #19
TODO: Still needs a test suite, I'll try to write some stuff tomorrow. In the mean time, here's a prototype.
Adds a directive to switch a set of classes in a DRY fashion by interacting with neighboring ui-sref directives.
The class to be used is an interpolated string, which is not $observed. There is no default, as I do not wish to tie this module to a particular CSS model or framework. A default may be configured in the future with a provider. As usual, multiple classes may be used, as Attributes.$addClass/$removeClass will separate classes on whitespace.
CAVEATS:
This is only capable of working as a parent of a ui-sref directive, or as a sibling directive on the same element. In the future, there may be a mechanism around this, but for the time being I can't think of what it would look like.
USAGE:
Sibling directive on same element as ui-sref:
--- OR ---
Ancestor directive of ui-sref: