Skip to content

Commit 4b4239f

Browse files
committed
feat(route): add route generation
Close #64
1 parent a8ee48b commit 4b4239f

14 files changed

+208
-10
lines changed

README.md

+42-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[![Dependency Status][david-badge]][david-badge-url]
55
[![devDependency Status][david-dev-badge]][david-dev-badge-url]
66
[![npm][npm-badge]][npm-badge-url]
7-
7+
88
Prototype of a CLI for Angular 2 applications based on the [ember-cli](http://www.ember-cli.com/) project.
99

1010
## Note
@@ -57,6 +57,44 @@ Add a new pipe with:
5757
ng generate pipe my-new-pipe
5858
```
5959

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

6199
### Creating a build
62100

@@ -69,17 +107,17 @@ The build artifacts will be stored in the `dist/` directory.
69107

70108
### Running tests
71109

72-
Before running the tests make sure that the project is built. To build the
110+
Before running the tests make sure that the project is built. To build the
73111
project once you can use:
74112

75113
```bash
76114
ng build
77115
```
78116

79-
With the project built in the `dist/` folder you can just run: `karma start`.
117+
With the project built in the `dist/` folder you can just run: `karma start`.
80118
Karma will run the tests and keep the browser open waiting to run again.
81119

82-
This will be easier when the command
120+
This will be easier when the command
83121
[ng test](https://github.com/angular/angular-cli/issues/70) is implemented.
84122

85123

+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) {
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
<script src="vendor/angular2/bundles/angular2-polyfills.js"></script>
88
{{content-for 'head'}}
99
<link rel="icon" type="image/x-icon" href="favicon.ico">

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,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,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,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)