Skip to content

Commit 2991dd7

Browse files
committed
feat(route): add route generation
Close #64
1 parent 1a56466 commit 2991dd7

20 files changed

+316
-9
lines changed

README.md

+45-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
[![Dependency Status][david-badge]][david-badge-url]
77
[![devDependency Status][david-dev-badge]][david-dev-badge-url]
88
[![npm][npm-badge]][npm-badge-url]
9-
9+
1010
Prototype of a CLI for Angular 2 applications based on the [ember-cli](http://www.ember-cli.com/) project.
1111

1212
## Note
@@ -59,6 +59,50 @@ Directive | `ng g directive my-new-directive`
5959
Pipe | `ng g pipe my-new-pipe`
6060
Service | `ng g service my-new-service`
6161

62+
### Generating a route
63+
64+
You can generate a new route by with the following command (note the singular
65+
used in `hero`):
66+
67+
```bash
68+
ng generate route hero
69+
```
70+
71+
This will create a folder with a routable component (`hero-root.component.ts`)
72+
with two sub-routes. The file structure will be as follows:
73+
74+
```
75+
...
76+
|-- app
77+
| |-- hero
78+
| | |-- hero-detail.component.html
79+
| | |-- hero-detail.component.css
80+
| | |-- hero-detail.component.spec.ts
81+
| | |-- hero-detail.component.ts
82+
| | |-- hero-list.component.html
83+
| | |-- hero-list.component.css
84+
| | |-- hero-list.component.spec.ts
85+
| | |-- hero-list.component.ts
86+
| | |-- hero-root.component.spec.ts
87+
| | |-- hero-root.component.ts
88+
| | |-- hero.service.spec.ts
89+
| | |-- hero.service.ts
90+
| |-- ...
91+
|-- app.ts
92+
...
93+
```
94+
95+
Afterwards to use the new route open your main app component, import
96+
`hero-root.component.ts` and add it in the route config:
97+
98+
```
99+
@RouteConfig([
100+
{path:'/hero/...', name: 'HeroRoot', component: HeroRoot}
101+
])
102+
```
103+
104+
Visiting `http://localhost:4200/hero` will show the hero list.
105+
62106

63107
### Creating a build
64108

addon/ng2/blueprints/ng2/files/karma-test-shim.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ System.import('angular2/platform/browser').then(function(browser_adapter) {
3737
});
3838

3939
function onlyAppFiles(filePath) {
40-
return /^\/base\/dist\/app\/(?!spec)([a-z0-9-_\/]+)\.js$/.test(filePath);
40+
return /^\/base\/dist\/app\/(?!.*\.spec\.js$)([a-z0-9-_\.\/]+)\.js$/.test(filePath);
4141
}
4242

4343
function onlySpecFiles(path) {

addon/ng2/blueprints/ng2/files/karma.conf.js

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ module.exports = function(config) {
1111
{pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: true},
1212
{pattern: 'node_modules/rxjs/bundles/Rx.js', included: true, watched: true},
1313
{pattern: 'node_modules/angular2/bundles/angular2.js', included: true, watched: true},
14+
{pattern: 'node_modules/angular2/bundles/http.dev.js', included: true, watched: true},
15+
{pattern: 'node_modules/angular2/bundles/router.dev.js', included: true, watched: true},
1416
{pattern: 'node_modules/angular2/bundles/testing.dev.js', included: true, watched: true},
1517

1618
{pattern: 'karma-test-shim.js', included: true, watched: true},
+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import {bootstrap} from 'angular2/platform/browser';
22
import {<%= jsComponentName %>App} from './app/<%= htmlComponentName %>';
3+
import {ROUTER_PROVIDERS} from 'angular2/router';
34

4-
5-
bootstrap(<%= jsComponentName %>App);
5+
bootstrap(<%= jsComponentName %>App, [
6+
ROUTER_PROVIDERS
7+
]);
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
<p>
22
<%= htmlComponentName %> Works!
3-
</p>
3+
</p>
4+
5+
<router-outlet></router-outlet>

addon/ng2/blueprints/ng2/files/src/app/__name__.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import {Component} from 'angular2/core';
2+
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
23

34

45
@Component({
56
selector: '<%= htmlComponentName %>-app',
67
providers: [],
78
templateUrl: 'app/<%= htmlComponentName %>.html',
8-
directives: [],
9+
directives: [ROUTER_DIRECTIVES],
910
pipes: []
1011
})
12+
@RouteConfig([
13+
14+
])
1115
export class <%= jsComponentName %>App {
1216
defaultMeaning: number = 42;
13-
17+
1418
meaningOfLife(meaning?: number) {
1519
return `The meaning of life is ${meaning || this.defaultMeaning}`;
1620
}

addon/ng2/blueprints/ng2/files/src/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="utf-8">
55
<title><%= jsComponentName %></title>
6-
<base href=".">
6+
<base href="/">
77
{{content-for 'head'}}
88
<link rel="icon" type="image/x-icon" href="favicon.ico">
99
</head>

addon/ng2/blueprints/route/files/src/app/__name__/__name__-detail.component.css

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<div *ngIf="<%= camelizedModuleName %>">
2+
<h3>"{{editName}}"</h3>
3+
<div>
4+
<label>Id:</label>
5+
{{<%= camelizedModuleName %>.id}}
6+
</div>
7+
<div>
8+
<label>Name:</label>
9+
<input [(ngModel)]="editName" placeholder="name"/>
10+
</div>
11+
<button (click)="save()">Save</button>
12+
<button (click)="cancel()">Cancel</button>
13+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {
2+
it,
3+
iit,
4+
describe,
5+
ddescribe,
6+
expect,
7+
inject,
8+
injectAsync,
9+
TestComponentBuilder,
10+
beforeEachProviders
11+
} from 'angular2/testing';
12+
import {provide} from 'angular2/core';
13+
import {<%= classifiedModuleName %>DetailComponent} from './<%= dasherizedModuleName %>-detail.component';
14+
15+
describe('<%= classifiedModuleName %>DetailComponent', () => {
16+
17+
beforeEachProviders(() => []);
18+
19+
it('should ...', injectAsync([TestComponentBuilder], (tcb:TestComponentBuilder) => {
20+
return tcb.createAsync(<%= classifiedModuleName %>DetailComponent).then((fixture) => {
21+
fixture.detectChanges();
22+
});
23+
}));
24+
25+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import {Component, OnInit} from 'angular2/core';
2+
import {<%= classifiedModuleName %>, <%= classifiedModuleName %>Service} from './<%= dasherizedModuleName %>.service';
3+
import {RouteParams, Router} from 'angular2/router';
4+
import {CanDeactivate, ComponentInstruction} from 'angular2/router';
5+
6+
@Component({
7+
templateUrl: 'app/<%= dasherizedModuleName %>/<%= dasherizedModuleName %>-detail.component.html',
8+
styleUrls: ['app/<%= dasherizedModuleName %>/<%= dasherizedModuleName %>-detail.component.css']
9+
})
10+
export class <%= classifiedModuleName %>DetailComponent implements OnInit, CanDeactivate {
11+
12+
<%= camelizedModuleName %>: <%= classifiedModuleName %>;
13+
editName: string;
14+
15+
constructor(
16+
private _service: <%= classifiedModuleName %>Service,
17+
private _router: Router,
18+
private _routeParams: RouteParams
19+
) { }
20+
21+
ngOnInit() {
22+
let id = +this._routeParams.get('id');
23+
this._service.get(id).then(<%= camelizedModuleName %> => {
24+
if (<%= camelizedModuleName %>) {
25+
this.editName = <%= camelizedModuleName %>.name;
26+
this.<%= camelizedModuleName %> = <%= camelizedModuleName %>;
27+
} else {
28+
this.gotoList();
29+
}
30+
});
31+
}
32+
33+
routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction): any {
34+
if (!this.<%= camelizedModuleName %> || this.<%= camelizedModuleName %>.name === this.editName) {
35+
return true;
36+
}
37+
38+
return new Promise<boolean>((resolve, reject) => resolve(window.confirm('Discard changes?')));
39+
}
40+
41+
cancel() {
42+
this.editName = this.<%= camelizedModuleName %>.name;
43+
this.gotoList();
44+
}
45+
46+
save() {
47+
this.<%= camelizedModuleName %>.name = this.editName;
48+
this.gotoList();
49+
}
50+
51+
gotoList() {
52+
this._router.navigate(['<%= classifiedModuleName %>List']);
53+
}
54+
}

addon/ng2/blueprints/route/files/src/app/__name__/__name__-list.component.css

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<h2><%= classifiedModuleName %> List</h2>
2+
3+
<ul>
4+
<li *ngFor="#<%= camelizedModuleName %> of <%= camelizedModuleName %>s">
5+
<a
6+
[routerLink]="['<%= classifiedModuleName %>Detail', { id: <%= camelizedModuleName %>.id }]">
7+
<strong>{{<%= camelizedModuleName %>.id}}</strong>
8+
-
9+
{{<%= camelizedModuleName %>.name}}
10+
</a>
11+
</li>
12+
</ul>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {
2+
it,
3+
iit,
4+
describe,
5+
ddescribe,
6+
expect,
7+
inject,
8+
injectAsync,
9+
TestComponentBuilder,
10+
beforeEachProviders
11+
} from 'angular2/testing';
12+
import {provide} from 'angular2/core';
13+
import {<%= classifiedModuleName %>ListComponent} from './<%= dasherizedModuleName %>-list.component';
14+
15+
describe('<%= classifiedModuleName %>ListComponent', () => {
16+
17+
beforeEachProviders(() => []);
18+
19+
it('should ...', injectAsync([TestComponentBuilder], (tcb:TestComponentBuilder) => {
20+
return tcb.createAsync(<%= classifiedModuleName %>ListComponent).then((fixture) => {
21+
fixture.detectChanges();
22+
});
23+
}));
24+
25+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {Component, OnInit} from 'angular2/core';
2+
import {<%= classifiedModuleName %>, <%= classifiedModuleName %>Service} from './<%= dasherizedModuleName %>.service';
3+
import {ROUTER_DIRECTIVES} from 'angular2/router';
4+
5+
@Component({
6+
templateUrl: 'app/<%= dasherizedModuleName %>/<%= dasherizedModuleName %>-list.component.html',
7+
styleUrls: ['app/<%= dasherizedModuleName %>/<%= dasherizedModuleName %>-list.component.css'],
8+
directives: [ROUTER_DIRECTIVES]
9+
})
10+
export class <%= classifiedModuleName %>ListComponent implements OnInit {
11+
<%= camelizedModuleName %>s: <%= classifiedModuleName %>[];
12+
constructor(
13+
private _service: <%= classifiedModuleName %>Service) {}
14+
ngOnInit() {
15+
this._service.getAll().then(<%= camelizedModuleName %>s => this.<%= camelizedModuleName %>s = <%= camelizedModuleName %>s);
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {Component} from 'angular2/core';
2+
import {RouteConfig, RouterOutlet} from 'angular2/router';
3+
4+
import {<%= classifiedModuleName %>ListComponent} from './<%= dasherizedModuleName %>-list.component';
5+
import {<%= classifiedModuleName %>DetailComponent} from './<%= dasherizedModuleName %>-detail.component';
6+
import {<%= classifiedModuleName %>Service} from './<%= dasherizedModuleName %>.service';
7+
8+
@Component({
9+
template: '<router-outlet></router-outlet>',
10+
providers: [<%= classifiedModuleName %>Service],
11+
directives: [RouterOutlet]
12+
})
13+
@RouteConfig([
14+
{path:'/', name: '<%= classifiedModuleName %>List', component: <%= classifiedModuleName %>ListComponent, useAsDefault: true},
15+
{path:'/:id', name: '<%= classifiedModuleName %>Detail', component: <%= classifiedModuleName %>DetailComponent}
16+
])
17+
export class <%= classifiedModuleName %>Root {
18+
constructor() {}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {describe, it, expect, beforeEachProviders, inject} from 'angular2/testing';
2+
import {provide} from 'angular2/core';
3+
import {<%= classifiedModuleName %>Service} from './<%= dasherizedModuleName %>.service';
4+
5+
describe('<%= classifiedModuleName %>Service', () => {
6+
7+
beforeEachProviders(() => [<%= classifiedModuleName %>Service]);
8+
9+
it('should get all <%= camelizedModuleName %>s', inject([<%= classifiedModuleName %>Service], (<%= camelizedModuleName %>Service:<%= classifiedModuleName %>Service) => {
10+
<%= camelizedModuleName %>Service.getAll().then(<%= camelizedModuleName %>s => expect(<%= camelizedModuleName %>s.length).toBe(3));
11+
}));
12+
13+
it('should get one <%= camelizedModuleName %>', inject([<%= classifiedModuleName %>Service], (<%= camelizedModuleName %>Service:<%= classifiedModuleName %>Service) => {
14+
<%= camelizedModuleName %>Service.get(1).then(<%= camelizedModuleName %> => expect(<%= camelizedModuleName %>.id).toBe(1));
15+
}));
16+
17+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {Injectable} from 'angular2/core';
2+
3+
export class <%= classifiedModuleName %> {
4+
constructor(public id: number, public name: string) { }
5+
}
6+
7+
@Injectable()
8+
export class <%= classifiedModuleName %>Service {
9+
getAll() { return promise; }
10+
get(id: number) {
11+
return promise.then(all => all.find(e => e.id === id));
12+
}
13+
}
14+
15+
let mock = [
16+
new <%= classifiedModuleName %>(1, 'one'),
17+
new <%= classifiedModuleName %>(2, 'two'),
18+
new <%= classifiedModuleName %>(3, 'three')
19+
];
20+
21+
let promise = Promise.resolve(mock);

addon/ng2/blueprints/route/index.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
var stringUtils = require('ember-cli/lib/utilities/string');
2+
3+
module.exports = {
4+
description: ''
5+
6+
//locals: function(options) {
7+
// // Return custom template variables here.
8+
// return {
9+
//
10+
// };
11+
//}
12+
13+
// afterInstall: function(options) {
14+
// // Perform extra work here.
15+
// }
16+
};

0 commit comments

Comments
 (0)