Skip to content

Instantly share code, notes, and snippets.

@hazeledmands
Created January 15, 2014 15:50
Show Gist options
  • Save hazeledmands/8438651 to your computer and use it in GitHub Desktop.
Save hazeledmands/8438651 to your computer and use it in GitHub Desktop.
ui-sref-nested implementation, while we wait for something to officially get rolled into angular-ui-router.
# Basically, ui-sref-active as implemented does not support nested states
# which is not particularly useful for many of the cases in this app.
#
# For more information take a look at this github issue:
# https://github.com/angular-ui/ui-router/issues/704
#
# And if it's fixed in core, then let's get rid of this directive! :D
app = angular.module 'lentilDirectives'
parseStateRef = (ref) ->
parsed = ref.replace(/\n/g, " ").match /^([^(]+?)\s*(\((.*)\))?$/
throw new Error("Invalid state ref '" + ref + "'") if not parsed or parsed.length isnt 4
state: parsed[1]
paramExpr: parsed[3] or null
equalForKeys = (a, b) ->
for key in Object.keys a
return false if a[key] isnt b[key]
return true
app.directive 'uiSrefNested', ['$state', '$stateParams', '$interpolate', ($state, $stateParams, $interpolate) ->
restrict: "A",
controller: ['$scope', '$element', '$attrs', ($scope, $element, $attrs) ->
state = null
params = {}
# There probably isn't much point in $observing this
activeClass = $interpolate($attrs.uiSrefNested || '', false)($scope)
ref = parseStateRef $attrs.uiSref
if ref.paramExpr?
$scope.$watch ref.paramExpr, ((newVal) ->
if newVal isnt params
params = newVal
state = $state.get ref.state
update()
), true
matchesParams = ->
!params or equalForKeys params, $stateParams
# Update route state
update = ->
if state? and $state.includes(state.name) and matchesParams()
$element.addClass(activeClass)
else
$element.removeClass(activeClass)
$scope.$on('$stateChangeSuccess', update)
]
]
// Generated by CoffeeScript 1.6.3
var app, equalForKeys, parseStateRef;
app = angular.module('lentilDirectives');
parseStateRef = function(ref) {
var parsed;
parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/);
if (!parsed || parsed.length !== 4) {
throw new Error("Invalid state ref '" + ref + "'");
}
return {
state: parsed[1],
paramExpr: parsed[3] || null
};
};
equalForKeys = function(a, b) {
var key, _i, _len, _ref;
_ref = Object.keys(a);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
key = _ref[_i];
if (a[key] !== b[key]) {
return false;
}
}
return true;
};
app.directive('uiSrefNested', [
'$state', '$stateParams', '$interpolate', function($state, $stateParams, $interpolate) {
return {
restrict: "A",
controller: [
'$scope', '$element', '$attrs', function($scope, $element, $attrs) {
var activeClass, matchesParams, params, ref, state, update;
state = null;
params = {};
activeClass = $interpolate($attrs.uiSrefNested || '', false)($scope);
ref = parseStateRef($attrs.uiSref);
if (ref.paramExpr != null) {
$scope.$watch(ref.paramExpr, (function(newVal) {
if (newVal !== params) {
params = newVal;
state = $state.get(ref.state);
return update();
}
}), true);
}
matchesParams = function() {
return !params || equalForKeys(params, $stateParams);
};
update = function() {
if ((state != null) && $state.includes(state.name) && matchesParams()) {
return $element.addClass(activeClass);
} else {
return $element.removeClass(activeClass);
}
};
return $scope.$on('$stateChangeSuccess', update);
}
]
};
}
]);
@mlegenhausen
Copy link

This directive does only work if an ref.paramExpr exists, if not it does nothing cause state is always null.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment