Skip to content

Commit 55f3d3d

Browse files
feat(urlRouter): Allow a rule to be deleted.
feat(urlRouter): Provide the new `rule` created by `.when()` to a callback fn test(urlRouter): convert to typescript
1 parent a94117d commit 55f3d3d

File tree

6 files changed

+61
-29
lines changed

6 files changed

+61
-29
lines changed

src/state/stateObject.ts

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export class State {
3131
public resolvables: Resolvable[];
3232
public resolvePolicy: any;
3333
public url: UrlMatcher;
34+
/** @hidden temporary place to put the rule registered with $urlRouter.when() */
35+
public _urlRule: any;
3436
public params: { [key: string]: Param };
3537
public views: { [key: string]: _ViewDeclaration; };
3638
public self: StateDeclaration;

src/state/stateQueueManager.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,6 @@ export class StateQueueManager {
9898
if ($state.$current.navigable !== state || !equalForKeys($match, $stateParams)) {
9999
$state.transitionTo(state, $match, { inherit: true, location: false, source: "url" });
100100
}
101-
}]);
101+
}], (rule) => state._urlRule = rule);
102102
}
103103
}

src/state/stateRegistry.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class StateRegistry {
3131

3232
listeners: StateRegistryListener[] = [];
3333

34-
constructor(urlMatcherFactory: UrlMatcherFactory, urlRouterProvider: UrlRouterProvider) {
34+
constructor(urlMatcherFactory: UrlMatcherFactory, private urlRouterProvider: UrlRouterProvider) {
3535
this.matcher = new StateMatcher(this.states);
3636
this.builder = new StateBuilder(this.matcher, urlMatcherFactory);
3737
this.stateQueue = new StateQueueManager(this.states, this.builder, urlRouterProvider, this.listeners);
@@ -130,7 +130,7 @@ export class StateRegistry {
130130
let deregistered = [state].concat(children).reverse();
131131

132132
deregistered.forEach(state => {
133-
state.url && state.url.config.$$removeRule();
133+
this.urlRouterProvider.removeRule(state._urlRule);
134134
delete this.states[state.name];
135135
});
136136

src/url/urlMatcher.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,11 @@ export class UrlMatcher {
112112

113113
/**
114114
* @param pattern The pattern to compile into a matcher.
115-
* @param config A configuration object hash
116-
* * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`.
117-
* * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`.
118-
*
119-
* @property {string} pattern The pattern that was passed into the constructor
115+
* @param config A configuration object
116+
* - `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`.
117+
* - `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`.
120118
*/
121-
constructor(pattern: string, public config: any) {
119+
constructor(pattern: string, public config?: any) {
122120
this.pattern = pattern;
123121
this.config = defaults(this.config, {
124122
params: {},

src/url/urlRouter.ts

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/** @module url */ /** for typedoc */
2-
import {extend, bindFunctions, IInjectable} from "../common/common";
2+
import {extend, bindFunctions, IInjectable, removeFrom} from "../common/common";
33
import {isFunction, isString, isDefined, isArray} from "../common/predicates";
44
import {UrlMatcher} from "./urlMatcher";
55
import {services, $InjectorLike, LocationServices} from "../common/coreservices";
@@ -125,13 +125,14 @@ export class UrlRouterProvider {
125125
return this;
126126
};
127127

128-
/** @hidden */
129-
private $$removeRule(rule) {
130-
let idx = this.rules.indexOf(rule);
131-
if (idx !== -1) {
132-
this.rules.splice(idx, 1);
133-
}
134-
return (idx !== -1);
128+
/**
129+
* Remove a rule previously registered
130+
*
131+
* @param rule the matcher rule that was previously registered using [[rule]]
132+
* @return true if the rule was found (and removed)
133+
*/
134+
removeRule(rule): boolean {
135+
return this.rules.length !== removeFrom(this.rules, rule).length;
135136
}
136137

137138
/**
@@ -202,10 +203,11 @@ export class UrlRouterProvider {
202203
*
203204
* @param what A pattern string to match, compiled as a [[UrlMatcher]].
204205
* @param handler The path (or function that returns a path) that you want to redirect your user to.
206+
* @param ruleCallback [optional] A callback that receives the `rule` registered with [[UrlMatcher.rule]]
205207
*
206208
* Note: the handler may also invoke arbitrary code, such as `$state.go()`
207209
*/
208-
when(what: (RegExp|UrlMatcher|string), handler: string|IInjectable) {
210+
when(what: (RegExp|UrlMatcher|string), handler: string|IInjectable, ruleCallback = function(rule) {}) {
209211
let {$urlMatcherFactory, $stateParams} = this;
210212
let redirect, handlerIsString = isString(handler);
211213

@@ -250,9 +252,7 @@ export class UrlRouterProvider {
250252
for (var n in check) {
251253
if (check[n]) {
252254
let rule = strategies[n](what, handler);
253-
if (check.matcher && what['config']) {
254-
what['config'].$$removeRule = () => this.$$removeRule(rule);
255-
}
255+
ruleCallback(rule);
256256
return this.rule(rule);
257257
}
258258
}

test/ng1/urlRouterSpec.js renamed to test/ng1/urlRouterSpec.ts

+40-8
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import ILocationService = angular.ILocationService;
2+
declare var html5Compat;
3+
import {UrlMatcher, services, UrlRouterProvider, UrlRouter, StateService} from "../../src/ng1";
4+
import ILocationProvider = angular.ILocationProvider;
5+
16
var module = angular.mock.module;
2-
var uiRouter = require("angular-ui-router");
3-
var UrlMatcher = uiRouter.UrlMatcher;
4-
var services = uiRouter.services;
57

68
describe("UrlRouter", function () {
79

8-
var $urp, $lp, $s, $ur, location, match, scope;
10+
var $urp: UrlRouterProvider, $lp: ILocationProvider,
11+
$s: StateService, $ur: UrlRouter, location: ILocationService, match, scope;
912

1013
describe("provider", function () {
1114

@@ -20,7 +23,7 @@ describe("UrlRouter", function () {
2023
inject(function($rootScope, $location, $injector) {
2124
scope = $rootScope.$new();
2225
location = $location;
23-
$ur = $injector.invoke($urp.$get, $urp);
26+
$ur = $injector.invoke($urp['$get'], $urp);
2427
});
2528
});
2629

@@ -71,9 +74,9 @@ describe("UrlRouter", function () {
7174
inject(function($rootScope, $location, $injector) {
7275
scope = $rootScope.$new();
7376
location = $location;
74-
$ur = $injector.invoke($urp.$get, $urp);
77+
$ur = $injector.invoke($urp['$get'], $urp);
7578
$s = $injector.get('$sniffer');
76-
$s.history = true;
79+
$s['history'] = true;
7780
});
7881
});
7982

@@ -155,6 +158,35 @@ describe("UrlRouter", function () {
155158
expect(called).toBeTruthy();
156159
expect(location.path()).toBe("/b4z");
157160
}));
161+
162+
163+
it('removeRule should remove a previously registered rule', function() {
164+
var count = 0, rule = function ($injector, $location) { count++; };
165+
$urp.rule(rule);
166+
167+
$ur.sync();
168+
expect(count).toBe(1);
169+
$ur.sync();
170+
expect(count).toBe(2);
171+
172+
$urp.removeRule(rule);
173+
$ur.sync();
174+
expect(count).toBe(2);
175+
});
176+
177+
it('when should provide the new rule to the callback argument', function() {
178+
var _rule, calls = 0;
179+
location.url('/foo');
180+
$urp.when('/foo', function() { calls++; }, function(rule) { _rule = rule; });
181+
expect(typeof _rule).toBe('function');
182+
183+
$ur.sync();
184+
expect(calls).toBe(1);
185+
186+
$urp.removeRule(_rule);
187+
$ur.sync();
188+
expect(calls).toBe(1);
189+
});
158190

159191
describe("location updates", function() {
160192
it('can push location changes', inject(function($urlRouter) {
@@ -248,7 +280,7 @@ describe("UrlRouter", function () {
248280

249281
it('should return URLs with #fragments when html5Mode is true & browser does not support pushState', inject(function($urlRouter) {
250282
$lp.html5Mode(true);
251-
$s.history = false;
283+
$s['history'] = false;
252284
expect(html5Compat($lp.html5Mode())).toBe(true);
253285
expect($urlRouter.href(new UrlMatcher('/hello/:name'), {name: 'world', '#': 'frag'})).toBe('#/hello/world#frag');
254286
}));

0 commit comments

Comments
 (0)