Skip to content

Commit cae4dc4

Browse files
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
1 parent 3c1bd0e commit cae4dc4

File tree

1 file changed

+36
-36
lines changed

1 file changed

+36
-36
lines changed

src/ng1/directives/stateDirectives.ts

+36-36
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ function stateContext(el: IAugmentedJQuery) {
3131
return path ? tail(path).state.name : undefined;
3232
}
3333

34+
function processedDef($state: StateService, $element: IAugmentedJQuery, def: Def): Def {
35+
let uiState = def.uiState || $state.current.name;
36+
let uiStateOpts = extend(defaultOpts($element, $state), def.uiStateOpts || {});
37+
let href = $state.href(uiState, def.uiStateParams, uiStateOpts);
38+
return { uiState, uiStateParams: def.uiStateParams, uiStateOpts, href };
39+
}
40+
3441
interface TypeInfo {
3542
attr: string;
3643
isAnchor: boolean;
@@ -58,8 +65,7 @@ function clickHook(el: IAugmentedJQuery, $state: StateService, $timeout: ITimeou
5865
if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || el.attr('target'))) {
5966
// HACK: This is to allow ng-clicks to be processed before the transition is initiated:
6067
var transition = $timeout(function () {
61-
let state = target.uiState || $state.current;
62-
$state.go(state, target.uiStateParams, target.uiStateOpts);
68+
$state.go(target.uiState, target.uiStateParams, target.uiStateOpts);
6369
});
6470
e.preventDefault();
6571

@@ -152,40 +158,37 @@ let uiSref = ['$uiRouter', '$timeout',
152158
restrict: 'A',
153159
require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
154160
link: function (scope: IScope, element: IAugmentedJQuery, attrs: any, uiSrefActive: any) {
155-
var ref = parseStateRef(attrs.uiSref);
156-
var type = getTypeInfo(element);
157-
var active = uiSrefActive[1] || uiSrefActive[0];
158-
var unlinkInfoFn: Function = null;
159-
var hookFn;
160-
161-
var def = { uiState: ref.state } as Def;
162-
def.uiStateOpts = extend(defaultOpts(element, $state), attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {});
163-
164-
var update = function (val?: any) {
165-
if (val) def.uiStateParams = angular.copy(val);
166-
let state = def.uiState || $uiRouter.globals.current;
167-
def.href = $state.href(state, def.uiStateParams, def.uiStateOpts);
168-
161+
let ref = parseStateRef(attrs.uiSref);
162+
let type = getTypeInfo(element);
163+
let active = uiSrefActive[1] || uiSrefActive[0];
164+
let unlinkInfoFn: Function = null;
165+
let hookFn;
166+
167+
let rawDef = { uiState: ref.state } as Def;
168+
let getDef = () => processedDef($state, element, rawDef);
169+
rawDef.uiStateOpts = attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {};
170+
171+
let update = function () {
172+
let def = getDef();
169173
if (unlinkInfoFn) unlinkInfoFn();
170-
if (active) unlinkInfoFn = active.$$addStateInfo(state, def.uiStateParams);
174+
if (active) unlinkInfoFn = active.$$addStateInfo(def.uiState, def.uiStateParams);
171175
if (def.href !== null) attrs.$set(type.attr, def.href);
172176
};
173177

174178
if (ref.paramExpr) {
175179
scope.$watch(ref.paramExpr, function (val) {
176-
if (val !== def.uiStateParams) update(val);
180+
rawDef.uiStateParams = angular.copy(val);
181+
update();
177182
}, true);
178-
def.uiStateParams = angular.copy(scope.$eval(ref.paramExpr));
183+
rawDef.uiStateParams = angular.copy(scope.$eval(ref.paramExpr));
179184
}
180185
update();
181186

182-
scope.$on('$destroy', <any> $uiRouter.stateRegistry.onStatesChanged(() => update()));
183-
scope.$on('$destroy', <any> $uiRouter.transitionService.onSuccess({}, () => update()));
187+
scope.$on('$destroy', <any> $uiRouter.stateRegistry.onStatesChanged(update));
188+
scope.$on('$destroy', <any> $uiRouter.transitionService.onSuccess({}, update));
184189

185190
if (!type.clickable) return;
186-
hookFn = clickHook(element, $state, $timeout, type, function () {
187-
return def;
188-
});
191+
hookFn = clickHook(element, $state, $timeout, type, getDef);
189192
element[element.on ? 'on' : 'bind']("click", hookFn);
190193
scope.$on('$destroy', function () {
191194
element[element.off ? 'off' : 'unbind']("click", hookFn);
@@ -236,41 +239,38 @@ let uiState = ['$uiRouter', '$timeout',
236239
link: function (scope: IScope, element: IAugmentedJQuery, attrs: any, uiSrefActive: any) {
237240
var type = getTypeInfo(element);
238241
var active = uiSrefActive[1] || uiSrefActive[0];
239-
var def = {} as Def;
240242
let inputAttrs = ['uiState', 'uiStateParams', 'uiStateOpts'];
241243
let watchDeregFns = inputAttrs.reduce((acc, attr) => (acc[attr] = noop, acc), {});
242244
var unlinkInfoFn: Function = null;
243245
var hookFn;
246+
var rawDef = {} as Def;
247+
let getDef = () => processedDef($state, element, rawDef);
244248

245249
function update() {
246-
let state = def.uiState || $uiRouter.globals.current;
247-
def.href = $state.href(state, def.uiStateParams, def.uiStateOpts);
248-
250+
let def = getDef();
249251
if (unlinkInfoFn) unlinkInfoFn();
250-
if (active) unlinkInfoFn = active.$$addStateInfo(state, def.uiStateParams);
252+
if (active) unlinkInfoFn = active.$$addStateInfo(def.uiState, def.uiStateParams);
251253
if (def.href) attrs.$set(type.attr, def.href);
252254
}
253255

254256
inputAttrs.forEach((field) => {
255-
def[field] = attrs[field] ? scope.$eval(attrs[field]) : null;
257+
rawDef[field] = attrs[field] ? scope.$eval(attrs[field]) : null;
256258

257259
attrs.$observe(field, (expr) => {
258260
watchDeregFns[field]();
259261
watchDeregFns[field] = scope.$watch(expr, (newval) => {
260-
def[field] = newval;
262+
rawDef[field] = newval;
261263
update();
262264
}, true);
263265
})
264266
});
265267

266-
scope.$on('$destroy', <any> $uiRouter.stateRegistry.onStatesChanged(() => update()));
267-
scope.$on('$destroy', <any> $uiRouter.transitionService.onSuccess({}, () => update()));
268+
scope.$on('$destroy', <any> $uiRouter.stateRegistry.onStatesChanged(update));
269+
scope.$on('$destroy', <any> $uiRouter.transitionService.onSuccess({}, update));
268270
update();
269271

270272
if (!type.clickable) return;
271-
hookFn = clickHook(element, $state, $timeout, type, function () {
272-
return def;
273-
});
273+
hookFn = clickHook(element, $state, $timeout, type, getDef);
274274
element[element.on ? 'on' : 'bind']("click", hookFn);
275275
scope.$on('$destroy', function () {
276276
element[element.off ? 'off' : 'unbind']("click", hookFn);

0 commit comments

Comments
 (0)