From 5080b50327b6204a436976b99fe667c8be1ba668 Mon Sep 17 00:00:00 2001 From: Constantine Poltyrev Date: Wed, 10 Feb 2016 01:48:39 +0200 Subject: [PATCH] Current state reference via "." notation. --- src/stateDirectives.js | 11 +++++++++-- test/stateDirectivesSpec.js | 19 ++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/stateDirectives.js b/src/stateDirectives.js index b39f7b6c8..83234a60e 100644 --- a/src/stateDirectives.js +++ b/src/stateDirectives.js @@ -33,7 +33,7 @@ function clickHook(el, $state, $timeout, type, current) { if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || el.attr('target'))) { // HACK: This is to allow ng-clicks to be processed before the transition is initiated: var transition = $timeout(function() { - $state.go(target.state, target.params, target.options); + $state.go(target.state === '.' ? $state.current.name : target.state, target.params, target.options); }); e.preventDefault(); @@ -128,7 +128,7 @@ function $StateRefDirective($state, $timeout) { var update = function(val) { if (val) def.params = angular.copy(val); - def.href = $state.href(ref.state, def.params, def.options); + 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); @@ -139,6 +139,13 @@ function $StateRefDirective($state, $timeout) { def.params = angular.copy(scope.$eval(ref.paramExpr)); } update(); + if (ref.state === '.') { + scope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) { + if (fromState.name !== toState.name) { + update(); + } + }); + } if (!type.clickable) return; element.bind("click", clickHook(element, $state, $timeout, type, function() { return def; })); diff --git a/test/stateDirectivesSpec.js b/test/stateDirectivesSpec.js index a9c0f120f..cc8478e94 100644 --- a/test/stateDirectivesSpec.js +++ b/test/stateDirectivesSpec.js @@ -1,15 +1,15 @@ describe('uiStateRef', function() { - var timeoutFlush, el, el2, template, scope, document, _locationProvider; + var timeoutFlush, el, el2, el3, template, scope, document, _locationProvider; beforeEach(module('ui.router')); beforeEach(module(function($stateProvider, $locationProvider) { _locationProvider = $locationProvider; $stateProvider.state('top', { - url: '' + url: '?param' }).state('contacts', { - url: '/contacts', + url: '/contacts?param', template: 'Person ' }).state('contacts.item', { url: '/{id:int}', @@ -79,12 +79,14 @@ describe('uiStateRef', function() { function buildDOM($rootScope, $compile, $timeout) { el = angular.element('Details'); el2 = angular.element('Top'); + el3 = angular.element('Param 1'); scope = $rootScope; scope.contact = { id: 5 }; scope.$apply(); $compile(el)(scope); $compile(el2)(scope); + $compile(el3)(scope); scope.$digest(); timeoutFlush = function () { @@ -103,6 +105,7 @@ describe('uiStateRef', function() { it('should generate the correct href', function() { expect(el.attr('href')).toBe('#/contacts/5'); expect(el2.attr('href')).toBe('#'); + expect(el3.attr('href')).toBe('#?param=1'); }); it('should update the href when parameters change', function() { @@ -289,6 +292,16 @@ describe('uiStateRef', function() { expect($state.current.name).toEqual('top'); expect($stateParams).toEqualData({}); })); + + it('should not transition state and change state params on "." pesudostate click', inject(function($state, $stateParams, $q){ + triggerClick(el); + timeoutFlush(); + triggerClick(el3); + timeoutFlush(); + $q.flush(); + expect($state.current.name).toEqual('contacts.item.detail'); + expect($stateParams).toEqualData({param: '1', id: 5}); + })); }); describe('links with dynamic state definitions', function () {