Skip to content

Commit

Permalink
change: convert to TypeScript and move definition to default property.
Browse files Browse the repository at this point in the history
  • Loading branch information
nonplus committed Oct 11, 2016
1 parent 5a73361 commit 8b15899
Show file tree
Hide file tree
Showing 11 changed files with 560 additions and 397 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
src/**/*.js
test/**/*.js
39 changes: 29 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,36 +25,39 @@ var app = angular.module('myApp', ['ng', 'ui.router.default']);
Defining Default Child State
----------------------------

In your state definition for an abstract state, set the `abstract` property to the name of a child state (relative or absolute).
The child state name can be provided statically as a string dynamically as a function callback.
In your state definition for an abstract state, add a `default` property with the name of a child state (relative or absolute).
The child state name can be provided statically as a string or dynamically as a function callback.

When a state transtion targets this abstract state, it will be redirected to the default child state instead.

```javascript
$stateProvider
.state('parent', {
abstract: '.index',
abstract: true,
default: '.index',
template: '<ui-view/>'
})
.state('parent.index', {
...
// ...
})
.state('parent.page2', {
...
// ...
})
.state('another', {
abstract: ['$rootScope', function($rootScope) {
abstract: true,
default: ['$rootScope', function($rootScope) {
return $rootScope.edit ? '.edit' : '.display';
}]
})
.state('another.display', {
...
// ...
})
.state('another.edit', {
...
// ...
})
.state('anotherWithPromise',{
abstract: ['$q',function($q){
abstract: true,
default: ['$q',function($q){
var defer = $q.defer();
asyncFunctionThatReturnsPromise().then(function(){
defer.resolve('anotherWithPromise.details');
Expand All @@ -63,10 +66,26 @@ $stateProvider
}]
})
.state('anotherWithPromise.details',{
...
// ...
})
```

#### Older version (< 0.0.5)

Older versions of this module specified the default state by assigning it to the `abstract` property:

```javascript
$stateProvider
.state('parent', {
abstract: '.index',
template: '<ui-view/>'
})
// ...
```

This behavior is still supported, but is **deprecated**, because it causes TypeScript conflicts. It is recommended
that the `{ abstract: true, default: '.index' }` format is used instead.

Using Default Child State
-------------------------

Expand Down
31 changes: 18 additions & 13 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var git = require('gulp-git');
var bump = require('gulp-bump');
var filter = require('gulp-filter');
var tag_version = require('gulp-tag-version');
var eslint = require("gulp-eslint");
var tslint = require("gulp-tslint");
var runSequence = require('run-sequence');
var wrap = require("gulp-wrap");
var gutil = require('gulp-util');
Expand All @@ -21,7 +21,7 @@ gulp.task('bump-version', function () {
.pipe(gulp.dest('./'));
});

gulp.task('commit-changes', function () {
gulp.task('commit-changes', ['test'], function () {
return gulp.src('.')
.pipe(git.commit('Bumped version number', {args: '-a'}));
});
Expand All @@ -35,7 +35,7 @@ gulp.task('push-changes', function (cb) {
git.push('origin', 'master', cb);
});

gulp.task('release', ['test'], function (callback) {
gulp.task('release', ['ts-compile', 'test'], function (callback) {
runSequence(
'bump-version',
'build',
Expand All @@ -56,12 +56,20 @@ gulp.task('tag-version', function() {
.pipe(tag_version());
});

gulp.task('build', function() {
gulp.task('build', ['ts-compile'], function() {
return gulp.src("src/angular-ui-router-default.js")
.pipe(wrap({ src: './build.txt' }, { info: require('./package.json') }))
.pipe(gulp.dest('.'));
});

gulp.task('ts-compile', function() {
var ts = require('gulp-typescript');
var tsProject = ts.createProject('tsconfig.json');
return tsProject.src(['src/**/*.ts', 'test/**/*.ts'])
.pipe(tsProject()).js
.pipe(gulp.dest('.'));
});

gulp.task('serve', serve({
root: __dirname,
port: port,
Expand Down Expand Up @@ -105,14 +113,11 @@ gulp.task('watch', function() {

gulp.task('lint', function () {
return gulp.src([
"./src/**/*.js",
"./test/**/*.js"
"./src/**/*.ts",
"./test/**/*.ts"
])
.pipe(eslint())
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe(eslint.format())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last.
.pipe(eslint.failAfterError());
.pipe(tslint({
formatter: "verbose"
}))
.pipe(tslint.report());
});
10 changes: 10 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import angular = require("angular");

declare module 'angular' {
export namespace ui {
export type DefaultSpecifier = string | (() => string) | (() => ng.IPromise<string>);
interface IState {
default?: DefaultSpecifier
}
}
}
33 changes: 24 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@
"version": "0.0.4",
"description": "AngularJS module that adds support for specifying default child views for abstract states when using ui-router.",
"main": "angular-ui-router-default.js",
"types": "./index.d.ts",
"directories": {
"test": "test"
},
"scripts": {
"test": "./node_modules/karma/bin/karma start --browsers Firefox --single-run"
"ts-compile": "./node_modules/gulp/bin/gulp.js ts-compile",
"karma-test": "./node_modules/karma/bin/karma start --browsers Firefox --single-run",
"test": "npm run ts-compile && npm run karma-test"
},
"repository": {
"type": "git",
Expand All @@ -17,25 +23,34 @@
},
"homepage": "https://github.com/nonplus/angular-ui-router-default",
"devDependencies": {
"angular": "^1.3.15",
"angular-mocks": "^1.3.15",
"angular-ui-router": "^0.2.14",
"@types/angular-mocks": "^1.5",
"@types/jasmine": "^2.5.35",
"angular": "^1.5",
"angular-mocks": "^1.5",
"angular-ui-router": "^0.2.18",
"gulp": "^3.8.11",
"gulp-bump": "^0.3.0",
"gulp-eslint": "^3.0.1",
"gulp-filter": "^2.0.2",
"gulp-git": "^1.2.1",
"gulp-git": "^1.11.3",
"gulp-karma": "0.0.4",
"gulp-serve": "^0.3.1",
"gulp-tag-version": "^1.2.1",
"gulp-tslint": "^6.1.2",
"gulp-typescript": "^3.0.2",
"gulp-util": "^3.0.4",
"gulp-wrap": "^0.11.0",
"jasmine-core": "^2.3.2",
"jasmine-core": "^2.5.2",
"karma": "^0.12.31",
"karma-chrome-launcher": "^0.1.8",
"karma-firefox-launcher": "^0.1.7",
"karma-jasmine": "^0.3.5",
"karma-jasmine": "^0.3.8",
"lodash": "^3.8.0",
"run-sequence": "^1.1.0"
"run-sequence": "^1.2.2",
"tslint": "^3.15.1",
"typescript": "^2.0.3"
},
"dependencies": {
"@types/angular": "^1.5",
"@types/angular-ui-router": "^1.1"
}
}
3 changes: 2 additions & 1 deletion sample/app/contacts/contacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ angular.module('uiRouterSample.contacts', [

// By specifying the name of a child state, when the abstract state is activated, it
// will activate the specified child state instead.
abstract: '.list',
abstract: true,
default: '.list',

// This abstract state will prepend '/contacts' onto the urls of all its children.
url: '/contacts',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
/* global angular */
"use strict";

var moduleName = 'ui.router.default';

/* commonjs package manager support (eg componentjs) */
if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports){
declare var module, exports;
if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports) {
module.exports = moduleName;
}

var max_redirects = 10;
angular.module(moduleName, ['ui.router'])
.config(['$provide', function($provide) {
$provide.decorator('$state', ['$delegate', '$injector', '$q', function($delegate, $injector, $q) {
.config(['$provide', function($provide: ng.auto.IProvideService) {

$provide.decorator('$state', ['$delegate', '$injector', '$q', function(
$delegate: ng.ui.IStateService,
$injector: ng.auto.IInjectorService,
$q: ng.IQService
) {
var transitionTo = $delegate.transitionTo;
var pendingPromise;
$delegate.transitionTo = function(to, toParams, options) {
$delegate.transitionTo = function(to, toParams, options): ng.IPromise<any> {
var numRedirects = 0;
var $state = this;
var nextState = to.name || to;
Expand All @@ -20,16 +28,17 @@ angular.module(moduleName, ['ui.router'])

return fetchTarget();

function fetchTarget() {
function fetchTarget(): ng.IPromise<any> {
var target = $state.get(nextState, $state.$current);
nextState = (target|| {}).name;
nextState = (target || {}).name;

var absRedirectPromise = getAbstractRedirect(target);
pendingPromise = absRedirectPromise;
return $q.when(absRedirectPromise, abstractTargetResolved);
return $q.when(absRedirectPromise)
.then(abstractTargetResolved);

function abstractTargetResolved(abstractTarget) {
if(absRedirectPromise !== pendingPromise) {
if (absRedirectPromise !== pendingPromise) {
return $q.reject(new Error('transition superseded'));
}
// we didn't get anything from the abstract target
Expand All @@ -48,12 +57,14 @@ angular.module(moduleName, ['ui.router'])
numRedirects += 1;
}
}
function getAbstractRedirect(state) {
if (!state || !state.abstract || state.abstract === true) {

function getAbstractRedirect(state: ng.ui.IState) {
if (!state || !state.abstract || (state.abstract === true && !state.default)) {
return null;
}
return invokeAbstract(state.abstract).then(abstractInvoked);
function abstractInvoked(newState) {
return invokeAbstract(state).then(abstractInvoked);

function abstractInvoked(newState): string {
if (newState[0] === '.') {
return nextState + newState;
} else {
Expand All @@ -62,15 +73,25 @@ angular.module(moduleName, ['ui.router'])
}

}
function invokeAbstract(abstract) {
if (!angular.isString(abstract)) {
return $q.when($injector.invoke(abstract));

function invokeAbstract(state: ng.ui.IState) {
var defaultState: ng.ui.DefaultSpecifier;

if (state.default) {
defaultState = state.default;
} else {
defaultState = state.abstract as any;
}

if (!angular.isString(defaultState)) {
return $q.when($injector.invoke(defaultState));
} else {
return $q.when(abstract);
return $q.when(defaultState);
}
}

};

return $delegate;
}]);
}]);
Loading

0 comments on commit 8b15899

Please sign in to comment.