@@ -80,7 +80,7 @@ function $StateRefDirective($state, $timeout) {
80
80
81
81
return {
82
82
restrict : 'A' ,
83
- require : '?^uiSrefActive' ,
83
+ require : [ '?^uiSrefActive' , '?^uiSrefActiveEquals' ] ,
84
84
link : function ( scope , element , attrs , uiSrefActive ) {
85
85
var ref = parseStateRef ( attrs . uiSref ) ;
86
86
var params = null , url = null , base = stateContext ( element ) || $state . $current ;
@@ -103,8 +103,9 @@ function $StateRefDirective($state, $timeout) {
103
103
104
104
var newHref = $state . href ( ref . state , params , options ) ;
105
105
106
- if ( uiSrefActive ) {
107
- uiSrefActive . $$setStateInfo ( ref . state , params ) ;
106
+ var activeDirective = uiSrefActive [ 1 ] || uiSrefActive [ 0 ] ;
107
+ if ( activeDirective ) {
108
+ activeDirective . $$setStateInfo ( ref . state , params ) ;
108
109
}
109
110
if ( ! newHref ) {
110
111
nav = false ;
@@ -148,12 +149,19 @@ function $StateRefDirective($state, $timeout) {
148
149
* @restrict A
149
150
*
150
151
* @description
151
- * A directive working alongside ui-sref to add classes to an element when the
152
+ * A directive working alongside ui-sref to add classes to an element when the
152
153
* related ui-sref directive's state is active, and removing them when it is inactive.
153
- * The primary use-case is to simplify the special appearance of navigation menus
154
+ * The primary use-case is to simplify the special appearance of navigation menus
154
155
* relying on `ui-sref`, by having the "active" state's menu button appear different,
155
156
* distinguishing it from the inactive menu items.
156
157
*
158
+ * ui-sref-active can live on the same element as ui-sref or on a parent element. The first
159
+ * one found will be used.
160
+ *
161
+ * Only activates when the ui-sref's actual target state is active, *not* any of it's children.
162
+ * For adding a class based on active children use
163
+ * {@link ui.router.state.directive:ui-sref-active-equals ui-sref-active-equals}
164
+ *
157
165
* @example
158
166
* Given the following template:
159
167
* <pre>
@@ -163,8 +171,8 @@ function $StateRefDirective($state, $timeout) {
163
171
* </li>
164
172
* </ul>
165
173
* </pre>
166
- *
167
- * When the app state is "app.user", and contains the state parameter "user" with value "bilbobaggins",
174
+ *
175
+ * When the app state is "app.user", and contains the state parameter "user" with value "bilbobaggins",
168
176
* the resulting HTML will appear as (note the 'active' class):
169
177
* <pre>
170
178
* <ul>
@@ -173,10 +181,10 @@ function $StateRefDirective($state, $timeout) {
173
181
* </li>
174
182
* </ul>
175
183
* </pre>
176
- *
177
- * The class name is interpolated **once** during the directives link time (any further changes to the
178
- * interpolated value are ignored).
179
- *
184
+ *
185
+ * The class name is interpolated **once** during the directives link time (any further changes to the
186
+ * interpolated value are ignored).
187
+ *
180
188
* Multiple classes may be specified in a space-separated format:
181
189
* <pre>
182
190
* <ul>
@@ -186,18 +194,37 @@ function $StateRefDirective($state, $timeout) {
186
194
* </ul>
187
195
* </pre>
188
196
*/
189
- $StateActiveDirective . $inject = [ '$state' , '$stateParams' , '$interpolate' ] ;
190
- function $StateActiveDirective ( $state , $stateParams , $interpolate ) {
191
- return {
197
+
198
+ /**
199
+ * @ngdoc directive
200
+ * @name ui.router.state.directive:ui-sref-active-equals
201
+ *
202
+ * @requires ui.router.state.$state
203
+ * @requires ui.router.state.$stateParams
204
+ * @requires $interpolate
205
+ *
206
+ * @restrict A
207
+ *
208
+ * @description
209
+ * The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will also activate
210
+ * when any descendant state of the ui-sref's target is active. It uses `$state.includes(uiSrefState)`
211
+ * to check for activation.
212
+ *
213
+ */
214
+ $StateRefActiveDirective . $inject = [ '$state' , '$stateParams' , '$interpolate' ] ;
215
+ function $StateRefActiveDirective ( $state , $stateParams , $interpolate ) {
216
+ return {
192
217
restrict : "A" ,
193
- controller : [ '$scope' , '$element' , '$attrs' , function ( $scope , $element , $attrs ) {
218
+ controller : [ '$scope' , '$element' , '$attrs' , function ( $scope , $element , $attrs ) {
194
219
var state , params , activeClass ;
195
220
196
221
// There probably isn't much point in $observing this
197
- activeClass = $interpolate ( $attrs . uiSrefActive || '' , false ) ( $scope ) ;
222
+ // uiSrefActive and uiSrefActiveEquals share the same directive object with some
223
+ // slight difference in logic routing
224
+ activeClass = $interpolate ( $attrs . uiSrefActiveEquals || $attrs . uiSrefActive || '' , false ) ( $scope ) ;
198
225
199
- // Allow uiSref to communicate with uiSrefActive
200
- this . $$setStateInfo = function ( newState , newParams ) {
226
+ // Allow uiSref to communicate with uiSrefActive[Equals]
227
+ this . $$setStateInfo = function ( newState , newParams ) {
201
228
state = $state . get ( newState , stateContext ( $element ) ) ;
202
229
params = newParams ;
203
230
update ( ) ;
@@ -207,13 +234,21 @@ function $StateActiveDirective($state, $stateParams, $interpolate) {
207
234
208
235
// Update route state
209
236
function update ( ) {
210
- if ( $state . $current . self === state && matchesParams ( ) ) {
237
+ if ( isMatch ( ) ) {
211
238
$element . addClass ( activeClass ) ;
212
239
} else {
213
240
$element . removeClass ( activeClass ) ;
214
241
}
215
242
}
216
243
244
+ function isMatch ( ) {
245
+ if ( typeof $attrs . uiSrefActiveEquals !== 'undefined' ) {
246
+ return $state . $current . self === state && matchesParams ( ) ;
247
+ } else {
248
+ return $state . includes ( state . name ) && matchesParams ( ) ;
249
+ }
250
+ }
251
+
217
252
function matchesParams ( ) {
218
253
return ! params || equalForKeys ( params , $stateParams ) ;
219
254
}
@@ -223,4 +258,5 @@ function $StateActiveDirective($state, $stateParams, $interpolate) {
223
258
224
259
angular . module ( 'ui.router.state' )
225
260
. directive ( 'uiSref' , $StateRefDirective )
226
- . directive ( 'uiSrefActive' , $StateActiveDirective ) ;
261
+ . directive ( 'uiSrefActive' , $StateRefActiveDirective )
262
+ . directive ( 'uiSrefActiveEquals' , $StateRefActiveDirective ) ;
0 commit comments