├── .gitignore ├── README.md ├── bootstrap ├── .gitignore ├── .vscode │ └── tasks.json ├── package.json └── src │ ├── image │ └── still_3.jpg │ ├── index.1.html │ ├── index.2.html │ ├── index.html │ ├── jumbotron │ ├── index.1.html │ ├── index.html │ ├── jumbotron.css │ └── meetingup.svg │ ├── mystyle.css │ ├── sticky-footer │ ├── index.html │ └── sticky-footer.css │ └── test.jpg ├── ng2-quickstart ├── .gitignore ├── README.md ├── app │ ├── app.component.ts │ ├── app.module.ts │ └── main.ts ├── index.html ├── package.json ├── styles.css ├── systemjs.config.js ├── tsconfig.json └── typings.json ├── ng2-starter-webpack ├── .gitignore ├── package.json ├── src │ ├── app │ │ ├── app.bootstrap-picker.component.html.txt │ │ ├── app.bootstrap-picker.component.ts.txt │ │ ├── app.component.ts.txt │ │ ├── app.module.ts │ │ ├── datetime-picker.component.html.txt │ │ ├── datetime-picker.component.ts.txt │ │ └── ng-bootstrap │ │ │ ├── app.ngbootstrap.component.html │ │ │ ├── app.ngbootstrap.component.ts │ │ │ └── custom.datepickerI18n.ts │ ├── index.html │ ├── index.html.txt │ └── main.ts ├── testdatetimepicker.html ├── tsconfig.json ├── typings.d.ts ├── typings.json └── webpack.config.js ├── ng2-starter-webpack1-01 ├── .gitignore ├── README.md ├── package.json ├── src │ ├── app │ │ ├── README.md │ │ ├── app.component.css │ │ ├── app.component.html │ │ ├── app.component.ts │ │ └── app.module.ts │ ├── index.html │ ├── main.ts │ └── typings.d.ts ├── tsconfig.json ├── typings.json └── webpack.config.js ├── ng2-tour-of-heroes-systemjs ├── .gitignore ├── README.md ├── app │ ├── app.component.css │ ├── app.component.ts │ ├── app.module.ts │ ├── app.routing.module.ts │ ├── dashboard.component.css │ ├── dashboard.component.html │ ├── dashboard.component.ts │ ├── hero-detail.component.css │ ├── hero-detail.component.html │ ├── hero-detail.component.ts │ ├── hero-search.component.css │ ├── hero-search.component.html │ ├── hero-search.component.ts │ ├── hero-search.service.ts │ ├── hero.service.ts │ ├── hero.ts │ ├── heroes.component.css │ ├── heroes.component.html │ ├── heroes.component.ts │ ├── in-memory-data.service.ts │ ├── main.ts │ ├── mock-hero.ts │ └── rxjs-extensions.ts ├── copyfile.sh ├── index.html ├── package.json ├── styles.css ├── systemjs.config.js ├── tsconfig.json └── typings.json ├── ng2-tour-of-heroes-webpack ├── .gitignore ├── README.md ├── package.json ├── src │ ├── app │ │ ├── app.component.css │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── app.routing.module.ts │ │ ├── dashboard.component.css │ │ ├── dashboard.component.html │ │ ├── dashboard.component.ts │ │ ├── hero-detail.component.css │ │ ├── hero-detail.component.html │ │ ├── hero-detail.component.ts │ │ ├── hero-search.component.css │ │ ├── hero-search.component.html │ │ ├── hero-search.component.ts │ │ ├── hero-search.service.ts │ │ ├── hero.service.ts │ │ ├── hero.ts │ │ ├── heroes.component.css │ │ ├── heroes.component.html │ │ ├── heroes.component.ts │ │ ├── in-memory-data.service.ts │ │ ├── main.ts │ │ ├── mock-hero.ts │ │ └── rxjs-extensions.ts │ ├── index.html │ └── styles.css ├── tsconfig.json ├── typings.json └── webpack.config.js ├── ng2-tour-of-heroes ├── .gitignore ├── app.back │ ├── app.component.css │ ├── app.component.ts │ ├── app.module.ts │ ├── app.routing.module.ts │ ├── dashboard.component.css │ ├── dashboard.component.html │ ├── dashboard.component.ts │ ├── hero-detail.component.css │ ├── hero-detail.component.html │ ├── hero-detail.component.ts │ ├── hero-search.component.css │ ├── hero-search.component.html │ ├── hero-search.component.ts │ ├── hero-search.service.ts │ ├── hero.service.ts │ ├── hero.ts │ ├── heroes.component.css │ ├── heroes.component.html │ ├── heroes.component.ts │ ├── in-memory-data.service.ts │ ├── main.ts │ ├── mock-hero.ts │ └── rxjs-extensions.ts ├── copyfile.sh.back ├── index.html.back ├── package.json ├── package.json.bak ├── src │ ├── app │ │ ├── app.component.css │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── app.routing.module.ts │ │ ├── dashboard │ │ │ ├── dashboard.component.css │ │ │ ├── dashboard.component.html │ │ │ └── dashboard.component.ts │ │ ├── hero-detail │ │ │ ├── hero-detail.component.css │ │ │ ├── hero-detail.component.html │ │ │ └── hero-detail.component.ts │ │ ├── hero-search │ │ │ ├── hero-search.component.css │ │ │ ├── hero-search.component.html │ │ │ ├── hero-search.component.ts │ │ │ └── hero-search.service.ts │ │ ├── hero │ │ │ ├── hero.service.ts │ │ │ ├── hero.ts │ │ │ ├── in-memory-data.service.ts │ │ │ └── mock-hero.ts │ │ └── heroes │ │ │ ├── heroes.component.css │ │ │ ├── heroes.component.html │ │ │ └── heroes.component.ts │ ├── index.html │ ├── main.ts │ ├── rxjs-extensions.ts │ └── styles.css ├── styles.css.back ├── tsconfig.json ├── typings.json └── webpack.config.js └── typescript-demo ├── .gitignore ├── TsClass.ts ├── TsInterface.ts ├── greeter.html ├── greeter.ts ├── package.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /ng2-quickstart/node_modules 3 | /**/node_modules 4 | /**/typings 5 | *.log 6 | /angular2-webpack 7 | /rebirth 8 | /test-webpack 9 | /NiceFish 10 | *.zip 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular2 2 | It contains many projects of ng2. Updating... ... 3 | 4 | # ng2-quickstart 5 | Follow the official document. [refer to README.md](./ng2-quickstart/README.md) 6 | 7 | # ng2-starter-webpack1-01 8 | A simple webpack-starter [refer to README.md](./ng2-starter-webpack1-01/README.md) 9 | 10 | # ng2-tour-of-heroes 11 | Follow the official document. 12 | 注意ng2-tour-of-hero 使用webpack出现问题,不要参考, 谢谢!(Not used!) 13 | 14 | # ng2-tour-of-heroes-systemjs 15 | Follow the official document with systemjs. [angular.cn](https://angular.cn/docs/ts/latest/tutorial/) 16 | Refer to [refer to README.md](./ng2-tour-of-heroes-systemjs/README.md) 17 | 18 | # ng2-tour-of-heroes-webpack 19 | Using webpack to package heroes project. 20 | Refer to [refer to README.md](./ng2-tour-of-heroes-webpack/README.md) 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /bootstrap/.gitignore: -------------------------------------------------------------------------------- 1 | *.mp4 2 | 3 | -------------------------------------------------------------------------------- /bootstrap/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "0.1.0", 5 | "command": "Chrome", 6 | "windows": { 7 | "command": "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe" 8 | }, 9 | "args": ["${file}"], 10 | "showOutput": "always" 11 | } -------------------------------------------------------------------------------- /bootstrap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "version": "0.0.1", 4 | "description": "bootstrap study", 5 | "keywords": [ 6 | "bootstrap" 7 | ], 8 | "author": "tancolo", 9 | "license": "MIT", 10 | 11 | "dependencies": { 12 | "jquery": "^2.2.4", 13 | "bootstrap": "3.3.7", 14 | "bootstrap-social": "^5.1.1" 15 | }, 16 | "devDependencies": { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /bootstrap/src/image/still_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tancolo/angular2/8f4d0c484592ce06304cfe451dc43dd1b00e972d/bootstrap/src/image/still_3.jpg -------------------------------------------------------------------------------- /bootstrap/src/index.1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | bootstrap 9 | 10 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 |
Quick Float to left
30 | 31 |
Quick Float to right
32 | 33 |
34 | 35 |
36 | Quick Float to left 37 |
38 | 39 |
40 | Quick Float to right 41 |
42 | 43 |
44 | 45 | 46 | 47 |
48 |
49 |
50 | 51 |
52 | 53 | 54 |
55 | 56 |
57 | 58 | 59 |
60 | 61 |
62 |
63 | 64 |
65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /bootstrap/src/index.2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | bootstrap 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 59 | 60 | 61 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /bootstrap/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | bootstrap 9 | 10 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | 47 | 48 | 62 | 63 | 64 | 117 | 118 | 119 | 159 | 160 | 161 | 185 | 186 | 187 | 209 | 210 | 211 |

I'm Heading1 h1. I'm secondary Heading1 h1

212 |

I'm Heading2 h2. I'm secondary Heading2 h2

213 |

I'm Heading3 h3. I'm secondary Heading3 h3

214 |

I'm Heading4 h4. I'm secondary Heading4 h4

215 |
I'm Heading5 h5. I'm secondary Heading5 h5
216 |
I'm Heading6 h6. I'm secondary Heading1 h6
217 | 218 |

Left aligned text.

219 |

Center aligned text.

220 |

Right aligned text.

221 |

This content is muted

222 |

This content carries a primary class

223 |

This content carries a success class

224 |

This content carries a info class

225 |

This content carries a warning class

226 |

This content carries a danger class

227 | 228 | 229 |

Example of Definition List

230 | 231 |
232 |
Description 1
233 |
Item 1
234 |
Description 2
235 |
Item 2
236 |
237 | 238 |

Example of Horizontal Definition List

239 | 240 |
241 |
Description 1
242 |
Item 1
243 |
Description 2
244 |
Item 2
245 |
246 | 247 |
248 | 249 |
250 | 251 | 252 |
253 | 254 |
255 | 256 | 257 |

Example block-level help text here.

258 |
259 | 260 |
261 | 262 |
263 | 264 | 265 |
266 | 267 | 268 | 269 | 270 | 271 |
272 | 273 |
274 | 275 | 276 |
277 | 278 |
279 | 280 | 281 |
282 | 283 |
284 | 285 |
286 | 287 | 288 |
289 | 290 | 291 | 292 |
293 | Example of Help Text 294 | 295 | 296 | 297 | A longer block of help text that breaks onto a new line and may extend beyond one line. 298 | 299 | 300 |
301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | -------------------------------------------------------------------------------- /bootstrap/src/jumbotron/index.1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Meetingup 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 45 | 46 | 47 |
48 | 49 |
50 |

What do you love?

51 |

Do more of it with Meetingup

52 |

Sign up

53 |
54 |
55 | 56 |
57 | 58 |
59 |
60 |

Heading

61 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

62 |

View details »

63 |
64 |
65 |

Heading

66 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

67 |

View details »

68 |
69 |
70 |

Heading

71 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet 72 | risus. 73 |

74 |

View details »

75 |
76 |
77 | 78 |
79 | 80 |
81 | 82 |
83 | 84 |
85 |
86 |

Heading

87 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

88 |

View details »

89 |
90 |
91 |

Heading

92 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

93 |

View details »

94 |
95 |
96 |

Heading

97 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet 98 | risus. 99 |

100 |

View details »

101 |
102 |
103 | 104 |
105 | 106 |
107 | 108 |
109 | 110 |
111 |
112 |

Heading

113 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

114 |

View details »

115 |
116 |
117 |

Heading

118 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

119 |

View details »

120 |
121 |
122 |

Heading

123 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet 124 | risus. 125 |

126 |

View details »

127 |
128 |
129 | 130 |
131 | 132 |
133 | 134 | 135 | 147 | 148 | 149 | 151 | 152 | 153 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /bootstrap/src/jumbotron/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Jumbotron Template for Bootstrap 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | 36 | 37 | 62 | 63 | 64 |
65 |
66 |

Hello, world!

67 |

This is a template for a simple marketing or informational website. It includes a large callout called a jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique.

68 |

Learn more »

69 |
70 |
71 | 72 |
73 | 74 |
75 |
76 |

Heading

77 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

78 |

View details »

79 |
80 |
81 |

Heading

82 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

83 |

View details »

84 |
85 |
86 |

Heading

87 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet 88 | risus. 89 |

90 |

View details »

91 |
92 |
93 | 94 |
95 | 96 | 99 |
100 | 101 | 102 | 103 | 105 | 106 | 107 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /bootstrap/src/jumbotron/jumbotron.css: -------------------------------------------------------------------------------- 1 | /* Move down content because we have a fixed navbar that is 50px tall */ 2 | 3 | 4 | /*html { 5 | position: relative; 6 | min-height: 100%; 7 | }*/ 8 | 9 | body { 10 | padding-top: 73px; 11 | /*padding-bottom: 20px;*/ 12 | /* Margin bottom by footer height */ 13 | margin-bottom: 100px; 14 | } 15 | 16 | .navbar-default .navbar-brand { 17 | color: black; 18 | height: 73px; 19 | } 20 | 21 | @media (min-width: 992px) { 22 | .navbar-text-center { 23 | width: 100%; 24 | text-align: left; 25 | } 26 | } 27 | 28 | @media (min-width: 1200px) { 29 | .navbar-text-center { 30 | width: 100%; 31 | text-align: center; 32 | } 33 | } 34 | 35 | .navbar-height { 36 | height: 73px; 37 | display: -webkit-flex; 38 | display: flex; 39 | -webkit-align-items: center; 40 | align-items: center; 41 | -webkit-justify-content: center; 42 | justify-content: center; 43 | } 44 | 45 | .navbar-header { 46 | height: 73px; 47 | display: -webkit-flex; 48 | display: flex; 49 | -webkit-align-items: center; 50 | align-items: center; 51 | -webkit-justify-content: center; 52 | justify-content: center; 53 | } 54 | 55 | 56 | /*@media only screen and (min-width: 760px) { 57 | .logoMeetingup { 58 | -webkit-transform: translate(-50%, -50%); 59 | -ms-transform: translate(-50%, -50%); 60 | transform: translate(-50%, -50%); 61 | position: absolute; 62 | height: 44px; 63 | top: 54%; 64 | left: 50%; 65 | max-width: 25%; 66 | } 67 | }*/ 68 | 69 | @media (min-width: 768px) { 70 | .jumbotron { 71 | height: 358px; 72 | } 73 | } 74 | 75 | @media (min-width: 992px) { 76 | .jumbotron { 77 | height: 410px; 78 | } 79 | } 80 | 81 | @media (min-width: 1200px) { 82 | .jumbotron { 83 | height: 465px; 84 | } 85 | } 86 | 87 | 88 | /*.jumbotron { 89 | height: 465px; 90 | }*/ 91 | 92 | .jumbotron-container-background { 93 | background-image: url("../image/still_3.jpg"); 94 | background-repeat: no-repeat; 95 | background-size: 100%, 100%; 96 | } 97 | 98 | .container h1 { 99 | text-align: center; 100 | color: floralwhite; 101 | font-weight: 600; 102 | } 103 | 104 | @media (min-width: 768px) { 105 | .container h1 { 106 | margin-top: 54px; 107 | } 108 | .container .text--display1 { 109 | font-size: 33px; 110 | } 111 | } 112 | 113 | @media (min-width: 768px) and (min-width: 992px) { 114 | .container h1 { 115 | margin-top: 76px; 116 | } 117 | .container.text--display1 { 118 | font-size: 42px; 119 | } 120 | } 121 | 122 | @media (min-width: 992px) { 123 | .container h1 { 124 | margin-top: 98px; 125 | } 126 | .container .text--display1 { 127 | font-size: 56px; 128 | } 129 | } 130 | 131 | .container .text--big { 132 | font-size: 20px; 133 | line-height: 1.25; 134 | font-weight: 600; 135 | letter-spacing: -.02em; 136 | text-align: center !important; 137 | color: floralwhite; 138 | } 139 | 140 | 141 | /*.container p { 142 | text-align: center; 143 | color: floralwhite; 144 | }*/ 145 | 146 | .container-button-center { 147 | text-align: center; 148 | color: floralwhite; 149 | margin-top: 53px; 150 | } 151 | 152 | @media (max-width: 767px) { 153 | .btn-width { 154 | width: 363px; 155 | } 156 | } 157 | 158 | @media (min-width: 768px) { 159 | .btn-width { 160 | width: 282px; 161 | } 162 | } 163 | 164 | .btn-shape { 165 | padding: .75em .75em; 166 | font-size: 16px; 167 | font-weight: 600; 168 | line-height: 1.45; 169 | min-height: 36px; 170 | height: 48px 171 | } 172 | 173 | .footer { 174 | /*position: absolute;*/ 175 | /*bottom: 0;*/ 176 | width: 100%; 177 | /* Set the fixed height of the footer here */ 178 | height: 100px; 179 | background: #263238; 180 | color: floralwhite; 181 | } 182 | 183 | 184 | /* 185 | video wrap 186 | */ 187 | 188 | 189 | /*.homeVideoWrap { 190 | display: -webkit-box; 191 | display: -moz-box; 192 | display: box; 193 | display: -webkit-flex; 194 | display: -moz-flex; 195 | display: -ms-flexbox; 196 | display: flex; 197 | height: 54vh; 198 | min-height: 320px; 199 | max-height: 465px; 200 | overflow: hidden; 201 | position: relative; 202 | background-size: cover; 203 | background-position: center center; 204 | background-repeat: no-repeat; 205 | box-sizing: border-box; 206 | } 207 | 208 | #homeVideoWrap>.bounds { 209 | position: relative; 210 | z-index: 25; 211 | margin: 0 auto; 212 | } 213 | 214 | .align--center, 215 | .pagination { 216 | -webkit-align-self: center; 217 | align-self: center; 218 | -ms-flex-item-align: center; 219 | text-align: center!important; 220 | } 221 | 222 | .bounds { 223 | box-sizing: border-box; 224 | margin-left: auto; 225 | margin-right: auto; 226 | max-width: 840px; 227 | padding: 24px 16px 8px; 228 | width: 100%; 229 | }*/ -------------------------------------------------------------------------------- /bootstrap/src/jumbotron/meetingup.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 82 | 83 | -------------------------------------------------------------------------------- /bootstrap/src/mystyle.css: -------------------------------------------------------------------------------- 1 | /*.navbar-right { 2 | margin-right: 100px; 3 | }*/ -------------------------------------------------------------------------------- /bootstrap/src/sticky-footer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 28 |

Pin a fixed-height footer to the bottom of the viewport in desktop browsers with this custom HTML and CSS.

29 |

Use the sticky footer with a fixed navbar if need be, too.

30 |
31 | 32 | 33 |
34 | 35 |
36 |
37 |

Heading

38 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

39 |

View details »

40 |
41 |
42 |

Heading

43 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

44 |

View details »

45 |
46 |
47 |

Heading

48 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet 49 | risus. 50 |

51 |

View details »

52 |
53 |
54 | 55 |
56 | 57 |
58 | 59 |
60 | 61 |
62 |
63 |

Heading

64 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

65 |

View details »

66 |
67 |
68 |

Heading

69 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

70 |

View details »

71 |
72 |
73 |

Heading

74 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet 75 | risus. 76 |

77 |

View details »

78 |
79 |
80 | 81 |
82 | 83 |
84 | 85 |
86 | 87 |
88 |
89 |

Heading

90 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

91 |

View details »

92 |
93 |
94 |

Heading

95 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

96 |

View details »

97 |
98 |
99 |

Heading

100 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet 101 | risus. 102 |

103 |

View details »

104 |
105 |
106 | 107 |
108 | 109 |
110 | 111 | 112 | 113 | 118 | 119 | 120 | 122 | 123 | 124 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /bootstrap/src/sticky-footer/sticky-footer.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer styles 2 | -------------------------------------------------- */ 3 | html { 4 | position: relative; 5 | min-height: 100%; 6 | } 7 | body { 8 | /* Margin bottom by footer height */ 9 | margin-bottom: 60px; 10 | } 11 | .footer { 12 | position: absolute; 13 | bottom: 0; 14 | width: 100%; 15 | /* Set the fixed height of the footer here */ 16 | height: 60px; 17 | background-color: #f5f5f5; 18 | } 19 | 20 | 21 | /* Custom page CSS 22 | -------------------------------------------------- */ 23 | /* Not required for template or sticky footer method. */ 24 | 25 | .container { 26 | width: auto; 27 | max-width: 680px; 28 | padding: 0 15px; 29 | } 30 | .container .text-muted { 31 | margin: 20px 0; 32 | } 33 | -------------------------------------------------------------------------------- /bootstrap/src/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tancolo/angular2/8f4d0c484592ce06304cfe451dc43dd1b00e972d/bootstrap/src/test.jpg -------------------------------------------------------------------------------- /ng2-quickstart/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /typings 3 | /app/*.js 4 | /app/*.map 5 | 6 | -------------------------------------------------------------------------------- /ng2-quickstart/README.md: -------------------------------------------------------------------------------- 1 | # ng2-quickstart 2 | Follow the official document. 3 | https://angular.cn/docs/ts/latest/guide/setup.html 4 | 5 | Modify the package file, change the latest verson @angular@2.4.2 . It Works. 6 | ``` 7 | "dependencies": { 8 | "@angular/common": "2.4.2", 9 | "@angular/compiler": "2.4.2", 10 | "@angular/core": "2.4.2", 11 | "@angular/forms": "2.4.2", 12 | "@angular/http": "2.4.2", 13 | "@angular/platform-browser": "2.4.2", 14 | "@angular/platform-browser-dynamic": "2.4.2", 15 | "@angular/router": "3.4.2", 16 | "@angular/upgrade": "2.4.2", 17 | "angular-in-memory-web-api": "0.2.4", 18 | "bootstrap": "3.3.7", 19 | "core-js": "2.4.1", 20 | "reflect-metadata": "0.1.9", 21 | "rxjs": "5.0.3", 22 | "systemjs": "0.19.41", 23 | "zone.js": "0.7.4" 24 | }, 25 | "devDependencies": { 26 | "concurrently": "3.1.0", 27 | "lite-server": "2.2.2", 28 | "typescript": "2.1.4", 29 | "typings": "2.1.0" 30 | } 31 | ``` 32 | 33 | ## 如何使用 34 | 1) npm install 35 | 36 | 2) npm start 37 | 38 | 3) review the browser, change the file app.component.ts -> name = "what you want" 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /ng2-quickstart/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'my-app', 5 | template: ` 6 |

Hello {{name}}

7 | ` 8 | }) 9 | 10 | export class AppComponent { 11 | name = "@tancolo"; 12 | } -------------------------------------------------------------------------------- /ng2-quickstart/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {BrowserModule} from '@angular/platform-browser'; 3 | 4 | import {AppComponent} from './app.component'; 5 | 6 | @NgModule({ 7 | imports: [BrowserModule], 8 | declarations: [AppComponent], 9 | bootstrap: [AppComponent] 10 | }) 11 | 12 | export class AppModule {} -------------------------------------------------------------------------------- /ng2-quickstart/app/main.ts: -------------------------------------------------------------------------------- 1 | import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; 2 | 3 | import {AppModule} from './app.module' ; 4 | 5 | const platform = platformBrowserDynamic(); 6 | platform.bootstrapModule(AppModule); 7 | -------------------------------------------------------------------------------- /ng2-quickstart/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular2 QuickStart 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Loading... 30 | 31 | 32 | -------------------------------------------------------------------------------- /ng2-quickstart/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-quickstart", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ", 6 | "lite": "lite-server", 7 | "postinstall": "typings install", 8 | "tsc": "tsc", 9 | "tsc:w": "tsc -w", 10 | "typings": "typings" 11 | }, 12 | "license": "ISC", 13 | "dependencies": { 14 | "@angular/common": "2.4.2", 15 | "@angular/compiler": "2.4.2", 16 | "@angular/core": "2.4.2", 17 | "@angular/forms": "2.4.2", 18 | "@angular/http": "2.4.2", 19 | "@angular/platform-browser": "2.4.2", 20 | "@angular/platform-browser-dynamic": "2.4.2", 21 | "@angular/router": "3.4.2", 22 | "@angular/upgrade": "2.4.2", 23 | "angular-in-memory-web-api": "0.2.4", 24 | "bootstrap": "3.3.7", 25 | "core-js": "2.4.1", 26 | "reflect-metadata": "0.1.9", 27 | "rxjs": "5.0.3", 28 | "systemjs": "0.19.41", 29 | "zone.js": "0.7.4" 30 | }, 31 | "devDependencies": { 32 | "concurrently": "3.1.0", 33 | "lite-server": "2.2.2", 34 | "typescript": "2.1.4", 35 | "typings": "2.1.0" 36 | } 37 | } -------------------------------------------------------------------------------- /ng2-quickstart/styles.css: -------------------------------------------------------------------------------- 1 | /* Master Styles */ 2 | h1 { 3 | color: #369; 4 | font-family: Arial, Helvetica, sans-serif; 5 | font-size: 250%; 6 | } 7 | h2, h3 { 8 | color: #444; 9 | font-family: Arial, Helvetica, sans-serif; 10 | font-weight: lighter; 11 | } 12 | body { 13 | margin: 2em; 14 | } 15 | -------------------------------------------------------------------------------- /ng2-quickstart/systemjs.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * System configuration for Angular samples 3 | * Adjust as necessary for your application needs. 4 | */ 5 | (function (global) { 6 | System.config({ 7 | paths: { 8 | // paths serve as alias 9 | 'npm:': 'node_modules/' 10 | }, 11 | // map tells the System loader where to look for things 12 | map: { 13 | // our app is within the app folder 14 | app: 'app', 15 | // angular bundles 16 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js', 17 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js', 18 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', 19 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', 20 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', 21 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js', 22 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js', 23 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', 24 | // other libraries 25 | 'rxjs': 'npm:rxjs', 26 | 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api', 27 | }, 28 | // packages tells the System loader how to load when no filename and/or no extension 29 | packages: { 30 | app: { 31 | main: './main.js', 32 | defaultExtension: 'js' 33 | }, 34 | rxjs: { 35 | defaultExtension: 'js' 36 | }, 37 | 'angular-in-memory-web-api': { 38 | main: './index.js', 39 | defaultExtension: 'js' 40 | } 41 | } 42 | }); 43 | })(this); 44 | -------------------------------------------------------------------------------- /ng2-quickstart/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": false, 10 | "noImplicitAny": false 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ng2-quickstart/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "globalDependencies": { 3 | "core-js": "registry:dt/core-js#0.0.0+20160725163759", 4 | "jasmine": "registry:dt/jasmine#2.2.0+20160621224255", 5 | "node": "registry:dt/node#6.0.0+20160909174046" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ng2-starter-webpack/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | *.log 4 | /dist 5 | /src/app/*.js 6 | /src/*.js 7 | /typings 8 | -------------------------------------------------------------------------------- /ng2-starter-webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-starter-webpack", 3 | "version": "0.0.1", 4 | "description": "just for ng2 starter ", 5 | "keywords": [ 6 | "angular2", 7 | "webpack" 8 | ], 9 | "author": "tancolo", 10 | "license": "MIT", 11 | "scripts": { 12 | "build": "webpack --progress", 13 | "build:prod": "webpack -p --progress", 14 | "postinstall": "typings install", 15 | "server": "webpack-dev-server --inline --progress" 16 | }, 17 | "dependencies": { 18 | "@angular/common": "2.2.0", 19 | "@angular/compiler": "2.2.0", 20 | "@angular/core": "2.2.0", 21 | "@angular/forms": "2.2.0", 22 | "@angular/http": "2.2.0", 23 | "@angular/platform-browser": "2.2.0", 24 | "@angular/platform-browser-dynamic": "2.2.0", 25 | "@angular/router": "3.2.0", 26 | "@angular/upgrade": "2.2.0", 27 | "@ng-bootstrap/ng-bootstrap": "^1.0.0-alpha.14", 28 | "angular-in-memory-web-api": "0.1.1", 29 | "bootstrap": "^4.0.0-alpha.5", 30 | "core-js": "2.4.1", 31 | "reflect-metadata": "0.1.6", 32 | "rxjs": "5.0.0-beta.12", 33 | "zone.js": "0.6.25" 34 | }, 35 | "devDependencies": { 36 | "angular2-template-loader": "0.5.0", 37 | "raw-loader": "0.5.1", 38 | "html-webpack-plugin": "2.22.0", 39 | "ts-loader": "^0.9.5", 40 | "typescript": "^2.0.6", 41 | "typings": "^1.5.0", 42 | "webpack": "^1.13.3", 43 | "webpack-dev-server": "^1.16.2" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ng2-starter-webpack/src/app/app.bootstrap-picker.component.html.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

date1: {{date1}}

6 | 7 | 8 | 9 |

date2: {{date2}}

-------------------------------------------------------------------------------- /ng2-starter-webpack/src/app/app.bootstrap-picker.component.ts.txt: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'my-app', 5 | templateUrl: './app.bootstrap-picker.component.html' 6 | }) 7 | 8 | export class AppBootstrapPickerComponent { 9 | private datetime: string; 10 | 11 | showDateTime(datetime){ 12 | console.log('datetime: ', datetime); 13 | this.datetime = datetime; 14 | //this.datetime = datetime.valueOf(); 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /ng2-starter-webpack/src/app/app.component.ts.txt: -------------------------------------------------------------------------------- 1 | import {Component, ViewChild, ElementRef, OnInit, AfterViewInit} from '@angular/core'; 2 | import * as $ from 'jquery'; 3 | //import '../../node_modules/jquery-datetimepicker/build/jquery.datetimepicker.full.js'; 4 | 5 | @Component({ 6 | selector: 'my-app', 7 | template: ` 8 |

所选日期:

9 | 10 | ` 11 | }) 12 | 13 | export class AppComponent implements AfterViewInit, OnInit { 14 | ngAfterViewInit():void { 15 | console.log('debug:11 ', $('#datetimepicker1').val()); 16 | } 17 | ngOnInit():void { 18 | const currentDateTime = new Date(); 19 | console.log('debug: ', $('#datetimepicker1').val('hello')); 20 | //$.datetimepicker.setLocale('ch'); 21 | //$('#datetimepicker1').datetimepicker({ 22 | // onChangeDateTime: function(dp, $input){ 23 | // console.log('date-Time: ', $input.val()); 24 | // } 25 | //}); 26 | } 27 | } -------------------------------------------------------------------------------- /ng2-starter-webpack/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | import {BrowserModule} from '@angular/platform-browser'; 4 | import { NgbModule, NgbDatepickerI18n } from '@ng-bootstrap/ng-bootstrap'; 5 | import {AppNgBootstrapComponent} from './ng-bootstrap/app.ngbootstrap.component'; 6 | import {I18n} from "./ng-bootstrap/custom.datepickerI18n"; 7 | import {CustomDatepickerI18n} from "./ng-bootstrap/custom.datepickerI18n"; 8 | 9 | @NgModule({ 10 | imports: [BrowserModule, FormsModule, NgbModule.forRoot()], 11 | declarations: [AppNgBootstrapComponent], 12 | bootstrap: [AppNgBootstrapComponent], 13 | providers: [ 14 | I18n, 15 | {provide: NgbDatepickerI18n, useClass: CustomDatepickerI18n} 16 | ] 17 | }) 18 | export class AppModule{} -------------------------------------------------------------------------------- /ng2-starter-webpack/src/app/datetime-picker.component.html.txt: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 |
7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
-------------------------------------------------------------------------------- /ng2-starter-webpack/src/app/datetime-picker.component.ts.txt: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, EventEmitter, Output,Input, AfterViewChecked } from '@angular/core'; 2 | import * as $ from 'jquery'; 3 | import '../../node_modules/bootstrap/dist/js/bootstrap.js'; 4 | import '../../node_modules/moment/moment.js' 5 | import '../../node_modules/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js'; 6 | 7 | @Component({ 8 | selector: 'ng2-datetimepicker', 9 | templateUrl: './datetime-picker.component.html' 10 | }) 11 | export class DateTimePickerComponent implements OnInit, AfterViewChecked { 12 | private dateTime:string; 13 | private datetimepickerElement; 14 | @Input() ID: string; 15 | @Output() dateSelected:EventEmitter = new EventEmitter(); 16 | 17 | constructor() { 18 | console.log('ID: ', this.ID); 19 | } 20 | 21 | ngAfterViewChecked():void { 22 | console.log('ngAfterViewChecked: '); 23 | this.datetimepickerElement = $('#' + this.ID ); 24 | this.datetimepickerElement.datetimepicker({ 25 | locale: 'en' 26 | }); 27 | this.datetimepickerElement.on('dp.change', e => { 28 | //console.log('onChange: ', e.date); 29 | this.dateTime = e.date; 30 | this.dateSelected.emit(this.dateTime); 31 | }); 32 | } 33 | 34 | ngOnInit():void { 35 | console.log('ngOnInit: '); 36 | //this.datetimepickerElement = $('#datetimepicker1'); 37 | //this.datetimepickerElement.datetimepicker({ 38 | // locale: 'en' 39 | //}); 40 | //this.datetimepickerElement.on('dp.change', e => { 41 | // //console.log('onChange: ', e.date); 42 | // this.dateTime = e.date; 43 | // this.dateSelected.emit(this.dateTime); 44 | //}); 45 | } 46 | } -------------------------------------------------------------------------------- /ng2-starter-webpack/src/app/ng-bootstrap/app.ngbootstrap.component.html: -------------------------------------------------------------------------------- 1 |

Ng Bootstrap Demo

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 |
45 |
46 | 49 |
51 | 52 |
53 | 54 |
56 | 57 |
58 |
59 |
60 |
61 | 62 |
63 |
64 | 日期: {{model | json}}
65 | 
-------------------------------------------------------------------------------- /ng2-starter-webpack/src/app/ng-bootstrap/app.ngbootstrap.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {I18n} from "./custom.datepickerI18n"; 3 | import {NgbDateStruct} from '@ng-bootstrap/ng-bootstrap'; 4 | @Component({ 5 | selector: 'ngbs-app', 6 | templateUrl: './app.ngbootstrap.component.html' 7 | }) 8 | 9 | export class AppNgBootstrapComponent { 10 | model; 11 | date: NgbDateStruct; 12 | 13 | constructor(private _i18n: I18n) { 14 | this.date = {year: 2015, month: 12, day: 8}; 15 | } 16 | 17 | set language(lang: string){ 18 | this._i18n.language = lang; 19 | } 20 | 21 | get language(){ 22 | return this._i18n.language; 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /ng2-starter-webpack/src/app/ng-bootstrap/custom.datepickerI18n.ts: -------------------------------------------------------------------------------- 1 | import { Component, Injectable } from '@angular/core'; 2 | import { NgbDatepickerI18n } from '@ng-bootstrap/ng-bootstrap'; 3 | 4 | const I18N_VALUES = { 5 | en: { 6 | weekdays: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'], 7 | months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 8 | }, 9 | zh: { 10 | //weekdays: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期天'], 11 | weekdays: ['Mon.', 'Tues.', 'Wed.', 'Thur.', 'Fri.', 'Sat.', 'Sun.'], 12 | months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], 13 | } 14 | }; 15 | 16 | // Define a service holding the language. You probably already have one if your app is i18ned. 17 | @Injectable() 18 | export class I18n { 19 | language = 'zh'; 20 | } 21 | 22 | // Define custom service providing the months and weekdays translations 23 | @Injectable() 24 | export class CustomDatepickerI18n extends NgbDatepickerI18n{ 25 | constructor(private _i18n: I18n) { 26 | super(); 27 | } 28 | 29 | getWeekdayName(weekday:number):string { 30 | return I18N_VALUES[this._i18n.language].weekdays[weekday - 1]; 31 | 32 | } 33 | 34 | getMonthName(month:number):string { 35 | return I18N_VALUES[this._i18n.language].months[month - 1]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ng2-starter-webpack/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular 2 starter webpack 6 | 7 | 8 | 9 | 10 | Loading... 11 | 12 | -------------------------------------------------------------------------------- /ng2-starter-webpack/src/index.html.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular 2 starter webpack 6 | 7 | 8 | 9 | 10 | 11 | 12 | Loading... 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ng2-starter-webpack/src/main.ts: -------------------------------------------------------------------------------- 1 | import 'core-js'; 2 | import 'reflect-metadata'; 3 | import 'zone.js/dist/zone'; 4 | 5 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 6 | import { AppModule } from './app/app.module'; 7 | 8 | const platform = platformBrowserDynamic(); 9 | platform.bootstrapModule(AppModule); -------------------------------------------------------------------------------- /ng2-starter-webpack/testdatetimepicker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular 2 starter webpack 6 | 7 | 8 | 9 |
10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 27 | -------------------------------------------------------------------------------- /ng2-starter-webpack/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions":{ 3 | "target": "es5", 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true 6 | } 7 | } -------------------------------------------------------------------------------- /ng2-starter-webpack/typings.d.ts: -------------------------------------------------------------------------------- 1 | declare var app: { 2 | environment: string; 3 | }; 4 | 5 | declare function require(id: string): any; 6 | -------------------------------------------------------------------------------- /ng2-starter-webpack/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "globalDependencies": { 3 | "core-js": "registry:dt/core-js#0.0.0+20160914114559", 4 | "jquery": "registry:dt/jquery#1.10.0+20160929162922" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ng2-starter-webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | module.exports = { 4 | 5 | entry: './src/main.ts', 6 | output: { 7 | path: './dist', 8 | filename: 'app.bundle.js' 9 | }, 10 | module: { 11 | loaders: [ 12 | {test: /\.component.ts$/, loader: 'ts!angular2-template'}, 13 | {test: /\.ts$/, exclude: /\.component.ts$/, loader: 'ts'}, 14 | {test: /\.html$/, loader: 'raw'}, 15 | {test: /\.css$/, loader: 'raw'} 16 | ] 17 | }, 18 | resolve: { 19 | extensions: ['', '.js', '.ts'] 20 | }, 21 | plugins: [ 22 | new HtmlWebpackPlugin({ 23 | template: './src/index.html' 24 | }) 25 | //new webpack.ProvidePlugin({ 26 | // '$': 'jquery', 27 | // 'jquery': 'jquery', 28 | // 'jQuery': 'jquery' 29 | //}) 30 | ] 31 | }; -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | *.log 4 | /dist 5 | /src/app/*.js 6 | /src/*.js 7 | /typings 8 | -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/README.md: -------------------------------------------------------------------------------- 1 | # ng2-starter-webpack1-01 2 | This is a basic webpack config. 3 | 4 | About the detail of the webpack,Please reference these articles 5 | 6 | [Angular2开发基础之TSC编译](http://www.jianshu.com/p/b12ccfdfb0c1) 7 | 8 | [Angular2开发基础之Webpack](http://www.jianshu.com/p/4b4264f045b7) 9 | 10 | # How to run 11 | 1) **npm install** 12 | 13 | 2) **npm run serve** 14 | http://localhost:8080/ 查看效果 15 | 16 | 3) **npm run build** 17 | 编译到dist目录,其中 `app.bundle.js` 以及`index.html`如何自动拷贝到`dist`中,参考文章: [Angular2开发基础之Webpack](http://www.jianshu.com/p/4b4264f045b7) 18 | 19 | 4) **npm run build:prod** 20 | 编译到dist目录,文件大小有明显压缩,参考文章: [Angular2开发基础之Webpack](http://www.jianshu.com/p/4b4264f045b7) 21 | 22 | 23 | # About package.json 24 | 依赖包版本,没有使用 `^`,`~`等符号,使用固定版本号,防止`npm install`后导致依赖包,相互不一致情况。 25 | 26 | ## script 27 | ``` 28 | "build": "webpack --progress", 29 | "build:prod": "webpack -p --progress", 30 | "postinstall": "typings install", 31 | "serve": "webpack-dev-server --inline --progress" 32 | ``` 33 | 基本含义自行google. 34 | 35 | 36 | # About webpack.config.js 37 | ``` 38 | var webpack = require('webpack'); 39 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 40 | module.exports = { 41 | 42 | entry: './src/main.ts', 43 | output: { 44 | path: './dist', 45 | filename: 'app.bundle.js' 46 | }, 47 | module: { 48 | loaders: [ 49 | { test: /\.component.ts$/, loader: 'ts!angular2-template' }, 50 | { test: /\.ts$/, exclude: /\.component.ts$/, loader: 'ts' }, 51 | { test: /\.html$/, loader: 'raw' }, 52 | { test: /\.css$/, loader: 'raw' } 53 | ] 54 | }, 55 | resolve: { 56 | extensions: ['', '.js', '.ts'] 57 | }, 58 | plugins: [ 59 | new HtmlWebpackPlugin({ 60 | template: './src/index.html' 61 | }) 62 | ] 63 | }; 64 | ``` 65 | [Angular2开发基础之Webpack](http://www.jianshu.com/p/4b4264f045b7) 有详细说明! 66 | 67 | ## About loader 68 | ``` 69 | { test: /\.component.ts$/, loader: 'ts!angular2-template' }, 70 | { test: /\.ts$/, exclude: /\.component.ts$/, loader: 'ts' }, 71 | ``` 72 | 区别是*.component.ts有可能包含html template, 而不是简单的 73 | ``` 74 | template: `

Hello World!

` 75 | ``` 76 | 而main.ts, vendor.ts(后续会介绍)是没有html模板的, 当然,可以只用一行替代:不考虑有没有html模板语句 77 | ``` 78 | { test: /\.ts$/, loader: 'ts!angular2-template' }, 79 | ``` 80 | 81 | # Component 结构 82 | 典型的Component结构是 xxx.component.html, xxx.component.css 83 | ``` 84 | @Component({ 85 | selector: 'my-app', 86 | templateUrl: './app.component.html', 87 | stylesUrl: ['./app.component.css'] 88 | }) 89 | ``` 90 | 91 | # typings.d.ts 92 | `declare function require(id: string): any;` 93 | 解决, 编译过程中出现 Can not find 'require' 问题。 94 | https://github.com/angular/angular-cli/issues/2221 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-starter-webpack", 3 | "version": "0.0.1", 4 | "description": "just for ng2 starter ", 5 | "keywords": [ 6 | "angular2", 7 | "webpack" 8 | ], 9 | "author": "tancolo", 10 | "license": "MIT", 11 | "scripts": { 12 | "build": "webpack --progress", 13 | "build:prod": "webpack -p --progress", 14 | "postinstall": "typings install", 15 | "serve": "webpack-dev-server --inline --progress" 16 | }, 17 | "dependencies": { 18 | "@angular/common": "2.4.2", 19 | "@angular/compiler": "2.4.2", 20 | "@angular/core": "2.4.2", 21 | "@angular/forms": "2.4.2", 22 | "@angular/http": "2.4.2", 23 | "@angular/platform-browser": "2.4.2", 24 | "@angular/platform-browser-dynamic": "2.4.2", 25 | "@angular/router": "3.4.2", 26 | "core-js": "2.4.1", 27 | "reflect-metadata": "0.1.9", 28 | "rxjs": "5.0.3", 29 | "zone.js": "0.7.4" 30 | }, 31 | "devDependencies": { 32 | "angular2-template-loader": "0.5.0", 33 | "html-webpack-plugin": "2.22.0", 34 | "raw-loader": "0.5.1", 35 | "ts-loader": "1.3.0", 36 | "typescript": "2.0.10", 37 | "typings": "2.1.0", 38 | "webpack": "1.14.0", 39 | "webpack-dev-server": "1.16.2" 40 | } 41 | } -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/src/app/README.md: -------------------------------------------------------------------------------- 1 | # angular2 2 | It contains many projects of ng2. Updating... ... 3 | 4 | # ng2-quickstart 5 | Follow the official document. [refer to README.md](./ng2-quickstart/README.md) 6 | 7 | # ng2-starter-webpack1-01 8 | A simple webpack-starter [refer to README.md](./ng2-starter-webpack1-01/README.md) 9 | 10 | # ng2-tour-of-hero 11 | Follow the official document. 12 | ## how to separate the ng2 ts files and js files into different folders 13 | [Please reference this article](http://www.jianshu.com/p/9bd75adaed6f) 14 | And you must execute the copyfile.sh after you changed some html or css files. 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/src/app/app.component.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: red; 3 | } 4 | 5 | p { 6 | font-size: 200%; 7 | } -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |

Hello World!

2 |

欢迎来到@tancolo github

-------------------------------------------------------------------------------- /ng2-starter-webpack1-01/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | // @Component({ 4 | // selector: 'my-app', 5 | // template: ` 6 | //

Hello World!

7 | //

欢迎来到@tancolo github

8 | // `, 9 | // styles: [` 10 | // h1 {color: red;} 11 | // p {font-size: 200%;} 12 | // `] 13 | // }) 14 | 15 | @Component({ 16 | selector: 'my-app', 17 | templateUrl: './app.component.html', 18 | styleUrls: ['./app.component.css'] 19 | }) 20 | export class AppComponent { 21 | constructor(){ 22 | console.log('AppComponent constructor'); 23 | } 24 | } -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import {BrowserModule} from '@angular/platform-browser'; 3 | 4 | import { AppComponent } from './app.component' 5 | 6 | @NgModule({ 7 | imports: [BrowserModule], 8 | declarations: [AppComponent], 9 | bootstrap: [AppComponent] 10 | }) 11 | export class AppModule{} -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | webpack01-Basic config 7 | 8 | 9 | 10 | Loading... 11 | 12 | 13 | -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/src/main.ts: -------------------------------------------------------------------------------- 1 | import 'core-js'; 2 | import 'reflect-metadata'; 3 | import 'zone.js/dist/zone'; 4 | 5 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 6 | import { AppModule } from './app/app.module'; 7 | 8 | const platform = platformBrowserDynamic(); 9 | platform.bootstrapModule(AppModule); -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | declare function require(id: string): any; 2 | -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions":{ 3 | "target": "es5", 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true 6 | } 7 | } -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "globalDependencies": { 3 | "core-js": "registry:dt/core-js#0.0.0+20160914114559" 4 | } 5 | } -------------------------------------------------------------------------------- /ng2-starter-webpack1-01/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | module.exports = { 4 | 5 | entry: './src/main.ts', 6 | output: { 7 | path: './dist', 8 | filename: 'app.bundle.js' 9 | }, 10 | module: { 11 | loaders: [ 12 | { test: /\.component.ts$/, loader: 'ts!angular2-template' }, 13 | { test: /\.ts$/, exclude: /\.component.ts$/, loader: 'ts' }, 14 | { test: /\.html$/, loader: 'raw' }, 15 | { test: /\.css$/, loader: 'raw' } 16 | ] 17 | }, 18 | resolve: { 19 | extensions: ['', '.js', '.ts'] 20 | }, 21 | plugins: [ 22 | new HtmlWebpackPlugin({ 23 | template: './src/index.html' 24 | }) 25 | ] 26 | }; -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /typings 3 | /app/*.js 4 | /app/*.map 5 | /dist 6 | 7 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/README.md: -------------------------------------------------------------------------------- 1 | # ng2-tour-of-heroes-systemjs 2 | 按照官方文档完结, 单独提取为systemjs目录! 3 | 4 | ## ng2-system遇到问题 5 | [ng2英雄指南相关问题](http://www.jianshu.com/p/9bd75adaed6f) 6 | 只要你是按照官方文档来操作,随着文件的增多,你会发现,如何让文件分类,并且让systemjs找到,是个大问题。 7 | 8 | ### how to separate the ng2 ts files and js files into different folders 9 | [Please reference this article](http://www.jianshu.com/p/9bd75adaed6f) 10 | And you must execute the copyfile.sh after you changed some html or css files. 11 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/app.component.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 1.2em; 3 | color: #999; 4 | margin-bottom: 0; 5 | } 6 | h2 { 7 | font-size: 2em; 8 | margin-top: 0; 9 | padding-top: 0; 10 | } 11 | nav a { 12 | padding: 5px 10px; 13 | text-decoration: none; 14 | margin-top: 10px; 15 | display: inline-block; 16 | background-color: #eee; 17 | border-radius: 4px; 18 | } 19 | nav a:visited, a:link { 20 | color: #607D8B; 21 | } 22 | nav a:hover { 23 | color: #039be5; 24 | background-color: #CFD8DC; 25 | } 26 | nav a.active { 27 | color: #039be5; 28 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | 4 | @Component({ 5 | moduleId: module.id, 6 | selector: 'my-app', 7 | template: ` 8 |

{{title}}

9 | 10 | 14 | 15 | `, 16 | styleUrls: ['app.component.css'] 17 | }) 18 | 19 | export class AppComponent { 20 | title = 'Tour of Heroes'; 21 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import './rxjs-extensions' 2 | 3 | import {NgModule} from '@angular/core'; 4 | import {BrowserModule} from '@angular/platform-browser'; 5 | import {FormsModule} from '@angular/forms'; 6 | import {HttpModule} from '@angular/http'; 7 | 8 | import {InMemoryWebApiModule} from 'angular-in-memory-web-api/in-memory-web-api.module'; 9 | import { InMemoryDataService } from './in-memory-data.service'; 10 | 11 | import {AppComponent} from './app.component'; 12 | import {DashboardComponent} from './dashboard.component'; 13 | import {HeroDetailComponent} from './hero-detail.component'; 14 | import {HeroesComponent} from './heroes.component'; 15 | import {HeroService} from "./hero.service"; 16 | 17 | import {AppRoutingModule} from './app.routing.module'; 18 | 19 | import {HeroSearchComponent} from "./hero-search.component"; 20 | 21 | @NgModule({ 22 | imports: [ 23 | BrowserModule, 24 | FormsModule, 25 | HttpModule, 26 | InMemoryWebApiModule.forRoot(InMemoryDataService), 27 | AppRoutingModule 28 | ], 29 | declarations: [ 30 | AppComponent, 31 | DashboardComponent, 32 | HeroDetailComponent, 33 | HeroesComponent, 34 | HeroSearchComponent 35 | ], 36 | bootstrap: [AppComponent], 37 | providers: [HeroService] 38 | }) 39 | 40 | export class AppModule { 41 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/app.routing.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {RouterModule, Routes} from '@angular/router'; 3 | 4 | import {DashboardComponent} from './dashboard.component'; 5 | import {HeroesComponent} from './heroes.component'; 6 | import {HeroDetailComponent} from './hero-detail.component'; 7 | 8 | const routes: Routes = [ 9 | { path: '', redirectTo: '/dashboard', pathMatch: 'full'}, 10 | { path: 'dashboard', component: DashboardComponent}, 11 | { path: 'detail/:id', component: HeroDetailComponent}, 12 | { path: 'heroes', component: HeroesComponent }, 13 | ]; 14 | 15 | @NgModule({ 16 | imports: [RouterModule.forRoot(routes)], 17 | exports: [RouterModule] 18 | }) 19 | export class AppRoutingModule {} 20 | 21 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/dashboard.component.css: -------------------------------------------------------------------------------- 1 | [class*='col-'] { 2 | float: left; 3 | } 4 | *, *:after, *:before { 5 | -webkit-box-sizing: border-box; 6 | -moz-box-sizing: border-box; 7 | box-sizing: border-box; 8 | } 9 | h3 { 10 | text-align: center; margin-bottom: 0; 11 | } 12 | [class*='col-'] { 13 | padding-right: 20px; 14 | padding-bottom: 20px; 15 | } 16 | [class*='col-']:last-of-type { 17 | padding-right: 0; 18 | } 19 | .grid { 20 | margin: 0; 21 | } 22 | .col-1-4 { 23 | width: 25%; 24 | } 25 | .module { 26 | padding: 20px; 27 | text-align: center; 28 | color: #eee; 29 | max-height: 120px; 30 | min-width: 120px; 31 | background-color: #607D8B; 32 | border-radius: 2px; 33 | } 34 | h4 { 35 | position: relative; 36 | } 37 | .module:hover { 38 | background-color: #EEE; 39 | cursor: pointer; 40 | color: #607d8b; 41 | } 42 | .grid-pad { 43 | padding: 10px 0; 44 | } 45 | .grid-pad > [class*='col-']:last-of-type { 46 | padding-right: 20px; 47 | } 48 | @media (max-width: 600px) { 49 | .module { 50 | font-size: 10px; 51 | max-height: 75px; } 52 | } 53 | @media (max-width: 1024px) { 54 | .grid { 55 | margin: 0; 56 | } 57 | .module { 58 | min-width: 60px; 59 | } 60 | } 61 | 62 | 63 | /* 64 | Copyright 2016 Google Inc. All Rights Reserved. 65 | Use of this source code is governed by an MIT-style license that 66 | can be found in the LICENSE file at http://angular.io/license 67 | */ -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/dashboard.component.html: -------------------------------------------------------------------------------- 1 |

Top Heroes

2 |
3 |
5 |
6 |

{{hero.name}}

7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/dashboard.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Router} from '@angular/router'; 3 | 4 | import {Hero} from './hero'; 5 | import {HeroService} from "./hero.service"; 6 | 7 | @Component({ 8 | moduleId: module.id, 9 | selector: 'my-dashboard', 10 | templateUrl: 'dashboard.component.html', 11 | styleUrls: ['dashboard.component.css'] 12 | }) 13 | export class DashboardComponent implements OnInit { 14 | heroes:Hero[] = []; 15 | 16 | constructor( 17 | private router:Router, 18 | private heroService:HeroService) { 19 | } 20 | 21 | ngOnInit():void { 22 | this.heroService.getHeroes() 23 | .then(heroes => this.heroes = heroes.slice(1, 5)); 24 | } 25 | 26 | gotoDetail(hero:Hero): void { 27 | let link = ['/detail', hero.id]; 28 | this.router.navigate(link); 29 | } 30 | 31 | 32 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/hero-detail.component.css: -------------------------------------------------------------------------------- 1 | label { 2 | display: inline-block; 3 | width: 3em; 4 | margin: .5em 0; 5 | color: #607D8B; 6 | font-weight: bold; 7 | } 8 | input { 9 | height: 2em; 10 | font-size: 1em; 11 | padding-left: .4em; 12 | } 13 | button { 14 | margin-top: 20px; 15 | font-family: Arial; 16 | background-color: #eee; 17 | border: none; 18 | padding: 5px 10px; 19 | border-radius: 4px; 20 | cursor: pointer; cursor: hand; 21 | } 22 | button:hover { 23 | background-color: #cfd8dc; 24 | } 25 | button:disabled { 26 | background-color: #eee; 27 | color: #ccc; 28 | cursor: auto; 29 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/hero-detail.component.html: -------------------------------------------------------------------------------- 1 |
2 |

{{hero.name}} details!

3 |
{{hero.id}}
4 |
5 | 6 | 7 |
8 | 9 | 10 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/hero-detail.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {ActivatedRoute, Params} from '@angular/router'; 3 | import {Location} from '@angular/common'; 4 | import {HeroService} from './hero.service'; 5 | import {Hero} from "./hero"; 6 | 7 | @Component({ 8 | moduleId: module.id, 9 | selector: 'my-hero-detail', 10 | templateUrl: 'hero-detail.component.html', 11 | styleUrls: ['hero-detail.component.css'] 12 | }) 13 | 14 | export class HeroDetailComponent implements OnInit{ 15 | hero: Hero; 16 | 17 | ngOnInit():void { 18 | this.route.params.forEach((params: Params) => { 19 | let id = +params['id']; 20 | this.heroService.getHero(id) 21 | .then(hero => this.hero = hero); 22 | }); 23 | } 24 | constructor( 25 | private heroService: HeroService, 26 | private route: ActivatedRoute, 27 | private location: Location 28 | ) {} 29 | 30 | goBack(): void{ 31 | this.location.back(); 32 | } 33 | 34 | save(): void{ 35 | this.heroService.update(this.hero) 36 | .then(() => this.goBack()); 37 | } 38 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/hero-search.component.css: -------------------------------------------------------------------------------- 1 | .search-result{ 2 | border-bottom: 1px solid gray; 3 | border-left: 1px solid gray; 4 | border-right: 1px solid gray; 5 | width:195px; 6 | height: 20px; 7 | padding: 5px; 8 | background-color: white; 9 | cursor: pointer; 10 | } 11 | #search-box{ 12 | width: 200px; 13 | height: 20px; 14 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/hero-search.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Hero Search

3 | 5 | 6 |
7 |
10 | {{hero.name}} 11 |
12 |
13 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/hero-search.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Router} from '@angular/router'; 3 | import {Observable} from 'rxjs/observable'; 4 | import {Subject} from 'rxjs/subject'; 5 | 6 | import {HeroSearchService} from './hero-search.service'; 7 | import {Hero} from './hero'; 8 | 9 | @Component({ 10 | moduleId: module.id, 11 | selector: 'hero-search', 12 | templateUrl: 'hero-search.component.html', 13 | styleUrls: ['hero-search.component.css'], 14 | providers: [HeroSearchService] 15 | }) 16 | export class HeroSearchComponent implements OnInit { 17 | heroes: Observable; 18 | private searchTerms = new Subject(); 19 | 20 | constructor( 21 | private heroSearchService: HeroSearchService, 22 | private router: Router){} 23 | 24 | search(term: string): void{ 25 | this.searchTerms.next(term); 26 | } 27 | 28 | ngOnInit():void { 29 | this.heroes = this.searchTerms 30 | .debounceTime(300) 31 | .distinctUntilChanged() 32 | .switchMap(term => 33 | term ? this.heroSearchService.search(term) : Observable.of([])) 34 | .catch(error => { 35 | console.log(error); 36 | return Observable.of([]) 37 | }); 38 | } 39 | 40 | gotoDetail(hero: Hero): void{ 41 | let link = ['/detail', hero.id]; 42 | this.router.navigate(link); 43 | } 44 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/hero-search.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response } from '@angular/http'; 3 | 4 | import { Observable } from 'rxjs'; 5 | 6 | import { Hero } from './hero'; 7 | 8 | @Injectable() 9 | export class HeroSearchService{ 10 | constructor(private http: Http){} 11 | 12 | search(term: string): Observable { 13 | return this.http 14 | .get(`app/heroes/?name=${term}`) 15 | .map((r: Response) => r.json().data as Hero[]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/hero.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Headers, Http } from '@angular/http'; 3 | 4 | import 'rxjs/add/operator/toPromise'; 5 | 6 | import { Hero } from './hero'; 7 | 8 | @Injectable() 9 | export class HeroService{ 10 | 11 | private headers = new Headers({'Content-Type': 'application/json'}); 12 | private heroesUrl = 'app/heroes'; // URL to web api 13 | constructor(private http: Http) { } 14 | 15 | getHeroes(): Promise { 16 | return this.http.get(this.heroesUrl) 17 | .toPromise() 18 | .then(response => response.json().data as Hero[]) 19 | .catch(this.handleError); 20 | } 21 | 22 | getHeroesslowly(): Promise{ 23 | //delay 2000ms 24 | return new Promise(resolve => setTimeout(resolve, 2000)) 25 | .then(() => this.getHeroes()); 26 | } 27 | 28 | getHero(id: number): Promise { 29 | return this.getHeroes() 30 | .then(heroes => heroes.find(hero => hero.id === id)) 31 | 32 | } 33 | 34 | private handleError(error: any): Promise { 35 | console.error('An error occurred', error); // for demo purposes only 36 | return Promise.reject(error.message || error); 37 | } 38 | 39 | update(hero: Hero): Promise { 40 | const url = `${this.heroesUrl}/${hero.id}`; 41 | return this.http 42 | .put(url, JSON.stringify(hero), {headers: this.headers}) 43 | .toPromise() 44 | .then(() => hero) 45 | .catch(this.handleError); 46 | } 47 | 48 | create(name: string): Promise { 49 | return this.http 50 | .post(this.heroesUrl, 51 | JSON.stringify({name: name}), 52 | {headers: this.headers}) 53 | .toPromise() 54 | .then(res => res.json().data) 55 | .catch(this.handleError); 56 | } 57 | 58 | delete(id: number): Promise { 59 | const url = `${this.heroesUrl}/${id}`; 60 | return this.http.delete(url, {headers: this.headers}) 61 | .toPromise() 62 | .then(() => null) 63 | .catch(this.handleError); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/hero.ts: -------------------------------------------------------------------------------- 1 | export class Hero { 2 | id: number; 3 | name: string; 4 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/heroes.component.css: -------------------------------------------------------------------------------- 1 | .selected { 2 | background-color: #CFD8DC !important; 3 | color: white; 4 | } 5 | .heroes { 6 | margin: 0 0 2em 0; 7 | list-style-type: none; 8 | padding: 0; 9 | width: 15em; 10 | } 11 | .heroes li { 12 | cursor: pointer; 13 | position: relative; 14 | left: 0; 15 | background-color: #EEE; 16 | margin: .5em; 17 | padding: .3em 0; 18 | height: 1.6em; 19 | border-radius: 4px; 20 | } 21 | .heroes li.selected:hover { 22 | background-color: #BBD8DC !important; 23 | color: white; 24 | } 25 | .heroes li:hover { 26 | color: #607D8B; 27 | background-color: #DDD; 28 | left: .1em; 29 | } 30 | .heroes .text { 31 | position: relative; 32 | top: -3px; 33 | } 34 | .heroes .badge { 35 | display: inline-block; 36 | font-size: small; 37 | color: white; 38 | padding: 0.8em 0.7em 0 0.7em; 39 | background-color: #607D8B; 40 | line-height: 1em; 41 | position: relative; 42 | left: -1px; 43 | top: -4px; 44 | height: 1.8em; 45 | margin-right: .8em; 46 | border-radius: 4px 0 0 4px; 47 | } 48 | 49 | button.delete { 50 | float:right; 51 | margin-top: 2px; 52 | margin-right: .8em; 53 | background-color: gray !important; 54 | color:white; 55 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/heroes.component.html: -------------------------------------------------------------------------------- 1 |

My Heroes

2 |
3 | 4 | 5 |
6 |
    7 |
  • 9 | {{hero.id}} 10 | {{hero.name}} 11 | 13 |
  • 14 | 15 | 16 |
    17 |

    18 | {{selectedHero.name | uppercase}} is my hero 19 |

    20 | 21 |
    22 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/heroes.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {Hero} from "./hero"; 3 | import {HEROES} from "./mock-hero"; 4 | import {HeroService} from "./hero.service"; 5 | import {OnInit} from '@angular/core' 6 | 7 | import {Router} from '@angular/router'; 8 | 9 | @Component({ 10 | moduleId: module.id, 11 | selector: 'my-heroes', 12 | templateUrl: 'heroes.component.html', 13 | styleUrls: ['heroes.component.css'] 14 | }) 15 | 16 | export class HeroesComponent implements OnInit { 17 | heroes:Hero[]; 18 | selectedHero:Hero; 19 | 20 | constructor(private router:Router, 21 | private heroService:HeroService) { 22 | } 23 | 24 | getHeroes():void { 25 | this.heroService.getHeroes() 26 | //this.heroService.getHeroesslowly() 27 | .then(heroes => this.heroes = heroes); 28 | } 29 | 30 | ngOnInit():void { 31 | this.getHeroes(); 32 | } 33 | 34 | onSelect(hero:Hero):void { 35 | this.selectedHero = hero; 36 | } 37 | 38 | gotoDetail():void { 39 | this.router.navigate(['/detail', this.selectedHero.id]); 40 | } 41 | 42 | add(name:string):void { 43 | name = name.trim(); 44 | if (!name) { 45 | return; 46 | } 47 | this.heroService.create(name) 48 | .then(hero => { 49 | this.heroes.push(hero); 50 | this.selectedHero = null; 51 | }); 52 | } 53 | 54 | delete(hero: Hero): void { 55 | this.heroService 56 | .delete(hero.id) 57 | .then(() => { 58 | this.heroes = this.heroes.filter(h => h != hero); 59 | if(this.selectedHero === hero){ 60 | this.selectedHero = null; 61 | } 62 | }) 63 | } 64 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/in-memory-data.service.ts: -------------------------------------------------------------------------------- 1 | import {InMemoryDbService} from 'angular-in-memory-web-api'; 2 | 3 | export class InMemoryDataService implements InMemoryDbService { 4 | createDb() { 5 | let heroes = [ 6 | {id: 11, name: 'Mr. Nice'}, 7 | {id: 12, name: 'Narco'}, 8 | {id: 13, name: 'Bombasto'}, 9 | {id: 14, name: 'Celeritas'}, 10 | {id: 15, name: 'Magneta'}, 11 | {id: 16, name: 'RubberMan'}, 12 | {id: 17, name: 'Dynama'}, 13 | {id: 18, name: 'Dr IQ'}, 14 | {id: 19, name: 'Magma'}, 15 | {id: 20, name: 'Tornado'} 16 | ]; 17 | return {heroes}; 18 | } 19 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/main.ts: -------------------------------------------------------------------------------- 1 | import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; 2 | 3 | import {AppModule} from './app.module' ; 4 | 5 | const platform = platformBrowserDynamic(); 6 | platform.bootstrapModule(AppModule); 7 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/mock-hero.ts: -------------------------------------------------------------------------------- 1 | import {Hero} from './hero' 2 | 3 | export const HEROES:Hero[] = [ 4 | {id: 11, name: 'Mr. Nice'}, 5 | {id: 12, name: 'Narco'}, 6 | {id: 13, name: 'Bombasto'}, 7 | {id: 14, name: 'Celeritas'}, 8 | {id: 15, name: 'Magneta'}, 9 | {id: 16, name: 'RubberMan'}, 10 | {id: 17, name: 'Dynama'}, 11 | {id: 18, name: 'Dr IQ'}, 12 | {id: 19, name: 'Magma'}, 13 | {id: 20, name: 'Tornado'} 14 | ]; 15 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/app/rxjs-extensions.ts: -------------------------------------------------------------------------------- 1 | // Observable class extensions 2 | import 'rxjs/add/observable/of'; 3 | import 'rxjs/add/observable/throw'; 4 | 5 | // Observable operators 6 | import 'rxjs/add/operator/catch'; 7 | import 'rxjs/add/operator/debounceTime'; 8 | import 'rxjs/add/operator/distinctUntilChanged'; 9 | import 'rxjs/add/operator/do'; 10 | import 'rxjs/add/operator/filter'; 11 | import 'rxjs/add/operator/map'; 12 | import 'rxjs/add/operator/switchMap'; -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/copyfile.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | cp ./app/*.css ./app/*.html ./dist/ 4 | 5 | 6 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular2 QuickStart 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Loading... 32 | 33 | 34 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-tour-of-heroes", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "start": "npm run cleandist && npm run moveassets && tsc && concurrently \"tsc -w\" \"lite-server\" ", 6 | "lite": "lite-server", 7 | "postinstall": "typings install", 8 | "tsc": "tsc", 9 | "tsc:w": "tsc -w", 10 | "typings": "typings", 11 | "cleandist": "rm -rf dist/*", 12 | "moveassets": "rsync -a --include='*.css' --include='*.html' --include='*/' --exclude='*' app/ dist/" 13 | }, 14 | "license": "ISC", 15 | "dependencies": { 16 | "@angular/common": "2.0.1", 17 | "@angular/compiler": "2.0.1", 18 | "@angular/core": "2.0.1", 19 | "@angular/forms": "2.0.1", 20 | "@angular/http": "2.0.1", 21 | "@angular/platform-browser": "2.0.1", 22 | "@angular/platform-browser-dynamic": "2.0.1", 23 | "@angular/router": "3.0.1", 24 | "@angular/upgrade": "2.0.1", 25 | "angular-in-memory-web-api": "0.1.1", 26 | "bootstrap": "3.3.7", 27 | "core-js": "2.4.1", 28 | "reflect-metadata": "0.1.8", 29 | "rxjs": "5.0.0-beta.12", 30 | "systemjs": "0.19.39", 31 | "zone.js": "0.6.25" 32 | }, 33 | "devDependencies": { 34 | "concurrently": "3.0.0", 35 | "lite-server": "2.2.2", 36 | "typescript": "2.0.3", 37 | "typings":"1.4.0", 38 | "onchange":"3.0.2" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/styles.css: -------------------------------------------------------------------------------- 1 | /* Master Styles */ 2 | h1 { 3 | color: #369; 4 | font-family: Arial, Helvetica, sans-serif; 5 | font-size: 250%; 6 | } 7 | h2, h3 { 8 | color: #444; 9 | font-family: Arial, Helvetica, sans-serif; 10 | font-weight: lighter; 11 | } 12 | body { 13 | margin: 2em; 14 | } 15 | body, input[text], button { 16 | color: #888; 17 | font-family: Cambria, Georgia; 18 | } 19 | /* . . . */ 20 | /* everywhere else */ 21 | * { 22 | font-family: Arial, Helvetica, sans-serif; 23 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/systemjs.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * System configuration for Angular samples 3 | * Adjust as necessary for your application needs. 4 | */ 5 | (function (global) { 6 | System.config({ 7 | paths: { 8 | // paths serve as alias 9 | 'npm:': 'node_modules/' 10 | }, 11 | // map tells the System loader where to look for things 12 | map: { 13 | // our app is within the app folder 14 | app: 'app', 15 | // angular bundles 16 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js', 17 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js', 18 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', 19 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', 20 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', 21 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js', 22 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js', 23 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', 24 | // other libraries 25 | 'rxjs': 'npm:rxjs', 26 | 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api', 27 | }, 28 | // packages tells the System loader how to load when no filename and/or no extension 29 | packages: { 30 | app: { 31 | main: './main.js', 32 | defaultExtension: 'js' 33 | }, 34 | rxjs: { 35 | defaultExtension: 'js' 36 | }, 37 | 'angular-in-memory-web-api': { 38 | main: './index.js', 39 | defaultExtension: 'js' 40 | } 41 | } 42 | }); 43 | })(this); 44 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": false, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": false, 10 | "noImplicitAny": false 11 | }, 12 | "exclude": [ 13 | "node_modules" 14 | ] 15 | 16 | } 17 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-systemjs/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "globalDependencies": { 3 | "core-js": "registry:dt/core-js#0.0.0+20160725163759", 4 | "jasmine": "registry:dt/jasmine#2.2.0+20160621224255", 5 | "node": "registry:dt/node#6.0.0+20160909174046" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /typings 3 | /app/*.js 4 | /app/*.map 5 | /dist 6 | 7 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/README.md: -------------------------------------------------------------------------------- 1 | # ng2-tour-of-heroes-webpack 2 | 在ng2-tour-of-heroes-systemjs基础上,使用webpack打包。 3 | 4 | 详细内容参考 [webpack打包ng2 英雄指南](http://www.jianshu.com/p/f5a21f18cfae) 5 | 6 | ## package.json 7 | 固定依赖包版本号,防止出现相互依赖而导致的各种问题! 8 | 9 | ## webpack.config.js 10 | webpack配置文件, 说明参考官方或是我的简书 [webpack打包ng2 英雄指南](http://www.jianshu.com/p/f5a21f18cfae) 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-tour-of-heroes", 3 | "version": "2.0.0", 4 | "scripts": { 5 | "build": "webpack --progress", 6 | "build:prod": "webpack -p --progress", 7 | "postinstall": "typings install", 8 | "server": "webpack-dev-server --inline --progress" 9 | }, 10 | "license": "ISC", 11 | "dependencies": { 12 | "@angular/common": "2.0.1", 13 | "@angular/compiler": "2.0.1", 14 | "@angular/core": "2.0.1", 15 | "@angular/forms": "2.0.1", 16 | "@angular/http": "2.0.1", 17 | "@angular/platform-browser": "2.0.1", 18 | "@angular/platform-browser-dynamic": "2.0.1", 19 | "@angular/router": "3.0.1", 20 | "@angular/upgrade": "2.0.1", 21 | "angular-in-memory-web-api": "0.1.1", 22 | "bootstrap": "3.3.7", 23 | "core-js": "2.4.1", 24 | "reflect-metadata": "0.1.8", 25 | "rxjs": "5.0.0-beta.12", 26 | "zone.js": "0.6.25" 27 | }, 28 | "devDependencies": { 29 | "angular2-template-loader": "0.4.0", 30 | "awesome-typescript-loader": "2.2.4", 31 | "css-loader": "0.23.1", 32 | "extract-text-webpack-plugin": "1.0.1", 33 | "html-loader": "0.4.3", 34 | "raw-loader": "0.5.1", 35 | "style-loader": "0.13.1", 36 | "html-webpack-plugin": "2.24.1", 37 | "ts-loader": "0.9.5", 38 | "typescript": "2.0.3", 39 | "typings": "1.4.0", 40 | "webpack": "1.13.3", 41 | "webpack-dev-server": "1.16.2" 42 | } 43 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/app.component.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 1.2em; 3 | color: #999; 4 | margin-bottom: 0; 5 | } 6 | h2 { 7 | font-size: 2em; 8 | margin-top: 0; 9 | padding-top: 0; 10 | } 11 | nav a { 12 | padding: 5px 10px; 13 | text-decoration: none; 14 | margin-top: 10px; 15 | display: inline-block; 16 | background-color: #eee; 17 | border-radius: 4px; 18 | } 19 | nav a:visited, a:link { 20 | color: #607D8B; 21 | } 22 | nav a:hover { 23 | color: #039be5; 24 | background-color: #CFD8DC; 25 | } 26 | nav a.active { 27 | color: #039be5; 28 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | 4 | @Component({ 5 | selector: 'my-app', 6 | template: ` 7 |

{{title}}

8 | 9 | 13 | 14 | `, 15 | styleUrls: ['./app.component.css'] 16 | }) 17 | 18 | export class AppComponent { 19 | title = 'Tour of Heroes'; 20 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import './rxjs-extensions' 2 | 3 | import {NgModule} from '@angular/core'; 4 | import {BrowserModule} from '@angular/platform-browser'; 5 | import {FormsModule} from '@angular/forms'; 6 | import {HttpModule} from '@angular/http'; 7 | 8 | import {InMemoryWebApiModule} from 'angular-in-memory-web-api/in-memory-web-api.module'; 9 | import { InMemoryDataService } from './in-memory-data.service'; 10 | 11 | import {AppComponent} from './app.component'; 12 | import {DashboardComponent} from './dashboard.component'; 13 | import {HeroDetailComponent} from './hero-detail.component'; 14 | import {HeroesComponent} from './heroes.component'; 15 | import {HeroService} from "./hero.service"; 16 | 17 | import {AppRoutingModule} from './app.routing.module'; 18 | 19 | import {HeroSearchComponent} from "./hero-search.component"; 20 | 21 | @NgModule({ 22 | imports: [ 23 | BrowserModule, 24 | FormsModule, 25 | HttpModule, 26 | InMemoryWebApiModule.forRoot(InMemoryDataService), 27 | AppRoutingModule 28 | ], 29 | declarations: [ 30 | AppComponent, 31 | DashboardComponent, 32 | HeroDetailComponent, 33 | HeroesComponent, 34 | HeroSearchComponent 35 | ], 36 | bootstrap: [AppComponent], 37 | providers: [HeroService] 38 | }) 39 | 40 | export class AppModule { 41 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/app.routing.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {RouterModule, Routes} from '@angular/router'; 3 | 4 | import {DashboardComponent} from './dashboard.component'; 5 | import {HeroesComponent} from './heroes.component'; 6 | import {HeroDetailComponent} from './hero-detail.component'; 7 | 8 | const routes: Routes = [ 9 | { path: '', redirectTo: '/dashboard', pathMatch: 'full'}, 10 | { path: 'dashboard', component: DashboardComponent}, 11 | { path: 'detail/:id', component: HeroDetailComponent}, 12 | { path: 'heroes', component: HeroesComponent }, 13 | ]; 14 | 15 | @NgModule({ 16 | imports: [RouterModule.forRoot(routes)], 17 | exports: [RouterModule] 18 | }) 19 | export class AppRoutingModule {} 20 | 21 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/dashboard.component.css: -------------------------------------------------------------------------------- 1 | [class*='col-'] { 2 | float: left; 3 | } 4 | *, *:after, *:before { 5 | -webkit-box-sizing: border-box; 6 | -moz-box-sizing: border-box; 7 | box-sizing: border-box; 8 | } 9 | h3 { 10 | text-align: center; margin-bottom: 0; 11 | } 12 | [class*='col-'] { 13 | padding-right: 20px; 14 | padding-bottom: 20px; 15 | } 16 | [class*='col-']:last-of-type { 17 | padding-right: 0; 18 | } 19 | .grid { 20 | margin: 0; 21 | } 22 | .col-1-4 { 23 | width: 25%; 24 | } 25 | .module { 26 | padding: 20px; 27 | text-align: center; 28 | color: #eee; 29 | max-height: 120px; 30 | min-width: 120px; 31 | background-color: #607D8B; 32 | border-radius: 2px; 33 | } 34 | h4 { 35 | position: relative; 36 | } 37 | .module:hover { 38 | background-color: #EEE; 39 | cursor: pointer; 40 | color: #607d8b; 41 | } 42 | .grid-pad { 43 | padding: 10px 0; 44 | } 45 | .grid-pad > [class*='col-']:last-of-type { 46 | padding-right: 20px; 47 | } 48 | @media (max-width: 600px) { 49 | .module { 50 | font-size: 10px; 51 | max-height: 75px; } 52 | } 53 | @media (max-width: 1024px) { 54 | .grid { 55 | margin: 0; 56 | } 57 | .module { 58 | min-width: 60px; 59 | } 60 | } 61 | 62 | 63 | /* 64 | Copyright 2016 Google Inc. All Rights Reserved. 65 | Use of this source code is governed by an MIT-style license that 66 | can be found in the LICENSE file at http://angular.io/license 67 | */ -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/dashboard.component.html: -------------------------------------------------------------------------------- 1 |

Top Heroes

2 |
3 |
5 |
6 |

{{hero.name}}

7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/dashboard.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Router} from '@angular/router'; 3 | 4 | import {Hero} from './hero'; 5 | import {HeroService} from "./hero.service"; 6 | 7 | @Component({ 8 | selector: 'my-dashboard', 9 | templateUrl: './dashboard.component.html', 10 | styleUrls: ['./dashboard.component.css'] 11 | }) 12 | export class DashboardComponent implements OnInit { 13 | heroes:Hero[] = []; 14 | 15 | constructor( 16 | private router:Router, 17 | private heroService:HeroService) { 18 | } 19 | 20 | ngOnInit():void { 21 | this.heroService.getHeroes() 22 | .then(heroes => this.heroes = heroes.slice(1, 5)); 23 | } 24 | 25 | gotoDetail(hero:Hero): void { 26 | let link = ['/detail', hero.id]; 27 | this.router.navigate(link); 28 | } 29 | 30 | 31 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/hero-detail.component.css: -------------------------------------------------------------------------------- 1 | label { 2 | display: inline-block; 3 | width: 3em; 4 | margin: .5em 0; 5 | color: #607D8B; 6 | font-weight: bold; 7 | } 8 | input { 9 | height: 2em; 10 | font-size: 1em; 11 | padding-left: .4em; 12 | } 13 | button { 14 | margin-top: 20px; 15 | font-family: Arial; 16 | background-color: #eee; 17 | border: none; 18 | padding: 5px 10px; 19 | border-radius: 4px; 20 | cursor: pointer; cursor: hand; 21 | } 22 | button:hover { 23 | background-color: #cfd8dc; 24 | } 25 | button:disabled { 26 | background-color: #eee; 27 | color: #ccc; 28 | cursor: auto; 29 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/hero-detail.component.html: -------------------------------------------------------------------------------- 1 |
2 |

{{hero.name}} details!

3 |
{{hero.id}}
4 |
5 | 6 | 7 |
8 | 9 | 10 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/hero-detail.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {ActivatedRoute, Params} from '@angular/router'; 3 | import {Location} from '@angular/common'; 4 | import {HeroService} from './hero.service'; 5 | import {Hero} from "./hero"; 6 | 7 | @Component({ 8 | selector: 'my-hero-detail', 9 | templateUrl: './hero-detail.component.html', 10 | styleUrls: ['./hero-detail.component.css'] 11 | }) 12 | 13 | export class HeroDetailComponent implements OnInit{ 14 | hero: Hero; 15 | 16 | ngOnInit():void { 17 | this.route.params.forEach((params: Params) => { 18 | let id = +params['id']; 19 | this.heroService.getHero(id) 20 | .then(hero => this.hero = hero); 21 | }); 22 | } 23 | constructor( 24 | private heroService: HeroService, 25 | private route: ActivatedRoute, 26 | private location: Location 27 | ) {} 28 | 29 | goBack(): void{ 30 | this.location.back(); 31 | } 32 | 33 | save(): void{ 34 | this.heroService.update(this.hero) 35 | .then(() => this.goBack()); 36 | } 37 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/hero-search.component.css: -------------------------------------------------------------------------------- 1 | .search-result{ 2 | border-bottom: 1px solid gray; 3 | border-left: 1px solid gray; 4 | border-right: 1px solid gray; 5 | width:195px; 6 | height: 20px; 7 | padding: 5px; 8 | background-color: white; 9 | cursor: pointer; 10 | } 11 | #search-box{ 12 | width: 200px; 13 | height: 20px; 14 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/hero-search.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Hero Search

3 | 5 | 6 |
7 |
10 | {{hero.name}} 11 |
12 |
13 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/hero-search.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Router} from '@angular/router'; 3 | import {Observable} from 'rxjs/observable'; 4 | import {Subject} from 'rxjs/subject'; 5 | 6 | import {HeroSearchService} from './hero-search.service'; 7 | import {Hero} from './hero'; 8 | 9 | @Component({ 10 | selector: 'hero-search', 11 | templateUrl: './hero-search.component.html', 12 | styleUrls: ['./hero-search.component.css'], 13 | providers: [HeroSearchService] 14 | }) 15 | export class HeroSearchComponent implements OnInit { 16 | heroes: Observable; 17 | private searchTerms = new Subject(); 18 | 19 | constructor( 20 | private heroSearchService: HeroSearchService, 21 | private router: Router){} 22 | 23 | search(term: string): void{ 24 | this.searchTerms.next(term); 25 | } 26 | 27 | ngOnInit():void { 28 | this.heroes = this.searchTerms 29 | .debounceTime(300) 30 | .distinctUntilChanged() 31 | .switchMap(term => 32 | term ? this.heroSearchService.search(term) : Observable.of([])) 33 | .catch(error => { 34 | console.log(error); 35 | return Observable.of([]) 36 | }); 37 | } 38 | 39 | gotoDetail(hero: Hero): void{ 40 | let link = ['/detail', hero.id]; 41 | this.router.navigate(link); 42 | } 43 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/hero-search.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response } from '@angular/http'; 3 | 4 | import { Observable } from 'rxjs'; 5 | 6 | import { Hero } from './hero'; 7 | 8 | @Injectable() 9 | export class HeroSearchService{ 10 | constructor(private http: Http){} 11 | 12 | search(term: string): Observable { 13 | return this.http 14 | .get(`app/heroes/?name=${term}`) 15 | .map((r: Response) => r.json().data as Hero[]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/hero.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Headers, Http } from '@angular/http'; 3 | 4 | import 'rxjs/add/operator/toPromise'; 5 | 6 | import { Hero } from './hero'; 7 | 8 | @Injectable() 9 | export class HeroService{ 10 | 11 | private headers = new Headers({'Content-Type': 'application/json'}); 12 | private heroesUrl = 'app/heroes'; // URL to web api 13 | constructor(private http: Http) { } 14 | 15 | getHeroes(): Promise { 16 | return this.http.get(this.heroesUrl) 17 | .toPromise() 18 | .then(response => response.json().data as Hero[]) 19 | .catch(this.handleError); 20 | } 21 | 22 | getHeroesslowly(): Promise{ 23 | //delay 2000ms 24 | return new Promise(resolve => setTimeout(resolve, 2000)) 25 | .then(() => this.getHeroes()); 26 | } 27 | 28 | getHero(id: number): Promise { 29 | return this.getHeroes() 30 | .then(heroes => heroes.find(hero => hero.id === id)) 31 | 32 | } 33 | 34 | private handleError(error: any): Promise { 35 | console.error('An error occurred', error); // for demo purposes only 36 | return Promise.reject(error.message || error); 37 | } 38 | 39 | update(hero: Hero): Promise { 40 | const url = `${this.heroesUrl}/${hero.id}`; 41 | return this.http 42 | .put(url, JSON.stringify(hero), {headers: this.headers}) 43 | .toPromise() 44 | .then(() => hero) 45 | .catch(this.handleError); 46 | } 47 | 48 | create(name: string): Promise { 49 | return this.http 50 | .post(this.heroesUrl, 51 | JSON.stringify({name: name}), 52 | {headers: this.headers}) 53 | .toPromise() 54 | .then(res => res.json().data) 55 | .catch(this.handleError); 56 | } 57 | 58 | delete(id: number): Promise { 59 | const url = `${this.heroesUrl}/${id}`; 60 | return this.http.delete(url, {headers: this.headers}) 61 | .toPromise() 62 | .then(() => null) 63 | .catch(this.handleError); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/hero.ts: -------------------------------------------------------------------------------- 1 | export class Hero { 2 | id: number; 3 | name: string; 4 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/heroes.component.css: -------------------------------------------------------------------------------- 1 | .selected { 2 | background-color: #CFD8DC !important; 3 | color: white; 4 | } 5 | .heroes { 6 | margin: 0 0 2em 0; 7 | list-style-type: none; 8 | padding: 0; 9 | width: 15em; 10 | } 11 | .heroes li { 12 | cursor: pointer; 13 | position: relative; 14 | left: 0; 15 | background-color: #EEE; 16 | margin: .5em; 17 | padding: .3em 0; 18 | height: 1.6em; 19 | border-radius: 4px; 20 | } 21 | .heroes li.selected:hover { 22 | background-color: #BBD8DC !important; 23 | color: white; 24 | } 25 | .heroes li:hover { 26 | color: #607D8B; 27 | background-color: #DDD; 28 | left: .1em; 29 | } 30 | .heroes .text { 31 | position: relative; 32 | top: -3px; 33 | } 34 | .heroes .badge { 35 | display: inline-block; 36 | font-size: small; 37 | color: white; 38 | padding: 0.8em 0.7em 0 0.7em; 39 | background-color: #607D8B; 40 | line-height: 1em; 41 | position: relative; 42 | left: -1px; 43 | top: -4px; 44 | height: 1.8em; 45 | margin-right: .8em; 46 | border-radius: 4px 0 0 4px; 47 | } 48 | 49 | button.delete { 50 | float:right; 51 | margin-top: 2px; 52 | margin-right: .8em; 53 | background-color: gray !important; 54 | color:white; 55 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/heroes.component.html: -------------------------------------------------------------------------------- 1 |

My Heroes

2 |
3 | 4 | 5 |
6 |
    7 |
  • 9 | {{hero.id}} 10 | {{hero.name}} 11 | 13 |
  • 14 | 15 | 16 |
    17 |

    18 | {{selectedHero.name | uppercase}} is my hero 19 |

    20 | 21 |
    22 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/heroes.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {Hero} from "./hero"; 3 | import {HEROES} from "./mock-hero"; 4 | import {HeroService} from "./hero.service"; 5 | import {OnInit} from '@angular/core' 6 | 7 | import {Router} from '@angular/router'; 8 | 9 | @Component({ 10 | selector: 'my-heroes', 11 | templateUrl: './heroes.component.html', 12 | styleUrls: ['./heroes.component.css'] 13 | }) 14 | 15 | export class HeroesComponent implements OnInit { 16 | heroes:Hero[]; 17 | selectedHero:Hero; 18 | 19 | constructor(private router:Router, 20 | private heroService:HeroService) { 21 | } 22 | 23 | getHeroes():void { 24 | this.heroService.getHeroes() 25 | //this.heroService.getHeroesslowly() 26 | .then(heroes => this.heroes = heroes); 27 | } 28 | 29 | ngOnInit():void { 30 | this.getHeroes(); 31 | } 32 | 33 | onSelect(hero:Hero):void { 34 | this.selectedHero = hero; 35 | } 36 | 37 | gotoDetail():void { 38 | this.router.navigate(['/detail', this.selectedHero.id]); 39 | } 40 | 41 | add(name:string):void { 42 | name = name.trim(); 43 | if (!name) { 44 | return; 45 | } 46 | this.heroService.create(name) 47 | .then(hero => { 48 | this.heroes.push(hero); 49 | this.selectedHero = null; 50 | }); 51 | } 52 | 53 | delete(hero: Hero): void { 54 | this.heroService 55 | .delete(hero.id) 56 | .then(() => { 57 | this.heroes = this.heroes.filter(h => h != hero); 58 | if(this.selectedHero === hero){ 59 | this.selectedHero = null; 60 | } 61 | }) 62 | } 63 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/in-memory-data.service.ts: -------------------------------------------------------------------------------- 1 | import {InMemoryDbService} from 'angular-in-memory-web-api'; 2 | 3 | export class InMemoryDataService implements InMemoryDbService { 4 | createDb() { 5 | let heroes = [ 6 | {id: 11, name: 'Mr. Nice'}, 7 | {id: 12, name: 'Narco'}, 8 | {id: 13, name: 'Bombasto'}, 9 | {id: 14, name: 'Celeritas'}, 10 | {id: 15, name: 'Magneta'}, 11 | {id: 16, name: 'RubberMan'}, 12 | {id: 17, name: 'Dynama'}, 13 | {id: 18, name: 'Dr IQ'}, 14 | {id: 19, name: 'Magma'}, 15 | {id: 20, name: 'Tornado'} 16 | ]; 17 | return {heroes}; 18 | } 19 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/main.ts: -------------------------------------------------------------------------------- 1 | import 'core-js'; 2 | import 'reflect-metadata'; 3 | import 'zone.js/dist/zone'; 4 | 5 | import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; 6 | 7 | import {AppModule} from './app.module' ; 8 | 9 | const platform = platformBrowserDynamic(); 10 | platform.bootstrapModule(AppModule); 11 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/mock-hero.ts: -------------------------------------------------------------------------------- 1 | import {Hero} from './hero' 2 | 3 | export const HEROES:Hero[] = [ 4 | {id: 11, name: 'Mr. Nice'}, 5 | {id: 12, name: 'Narco'}, 6 | {id: 13, name: 'Bombasto'}, 7 | {id: 14, name: 'Celeritas'}, 8 | {id: 15, name: 'Magneta'}, 9 | {id: 16, name: 'RubberMan'}, 10 | {id: 17, name: 'Dynama'}, 11 | {id: 18, name: 'Dr IQ'}, 12 | {id: 19, name: 'Magma'}, 13 | {id: 20, name: 'Tornado'} 14 | ]; 15 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/app/rxjs-extensions.ts: -------------------------------------------------------------------------------- 1 | // Observable class extensions 2 | import 'rxjs/add/observable/of'; 3 | import 'rxjs/add/observable/throw'; 4 | 5 | // Observable operators 6 | import 'rxjs/add/operator/catch'; 7 | import 'rxjs/add/operator/debounceTime'; 8 | import 'rxjs/add/operator/distinctUntilChanged'; 9 | import 'rxjs/add/operator/do'; 10 | import 'rxjs/add/operator/filter'; 11 | import 'rxjs/add/operator/map'; 12 | import 'rxjs/add/operator/switchMap'; -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular2 Heroes webapck 6 | 7 | 8 | 9 | 10 | 11 | 12 | Loading... 13 | 14 | 15 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/src/styles.css: -------------------------------------------------------------------------------- 1 | /* Master Styles */ 2 | h1 { 3 | color: #369; 4 | font-family: Arial, Helvetica, sans-serif; 5 | font-size: 250%; 6 | } 7 | h2, h3 { 8 | color: #444; 9 | font-family: Arial, Helvetica, sans-serif; 10 | font-weight: lighter; 11 | } 12 | body { 13 | margin: 2em; 14 | } 15 | body, input[text], button { 16 | color: #888; 17 | font-family: Cambria, Georgia; 18 | } 19 | /* . . . */ 20 | /* everywhere else */ 21 | * { 22 | font-family: Arial, Helvetica, sans-serif; 23 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": false, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": false, 10 | "noImplicitAny": false 11 | }, 12 | "exclude": [ 13 | "node_modules" 14 | ] 15 | 16 | } 17 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "globalDependencies": { 3 | "core-js": "registry:dt/core-js#0.0.0+20160725163759", 4 | "jasmine": "registry:dt/jasmine#2.2.0+20160621224255", 5 | "node": "registry:dt/node#6.0.0+20160909174046" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes-webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | 4 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 6 | 7 | module.exports = { 8 | 9 | entry: './src/app/main.ts', 10 | output: { 11 | path: root('dist'), 12 | filename: 'app.bundle.js' 13 | }, 14 | resolve: { 15 | extensions: ['', '.js', '.ts'] 16 | }, 17 | module: { 18 | loaders: [ 19 | { 20 | test: /\.ts$/, 21 | loaders: ['awesome-typescript-loader', 'angular2-template-loader'] 22 | }, 23 | { 24 | test: /\.css$/, 25 | exclude: root('src', 'app'), 26 | loader: ExtractTextPlugin.extract({fallbackLoader: 'style-loader', loader: ['css']}) 27 | }, 28 | 29 | // all css required in src/app files will be merged in js files 30 | { 31 | test: /\.css$/, 32 | include: root('src', 'app'), 33 | loader: 'raw' 34 | }, 35 | 36 | // support for .html as raw text 37 | { 38 | test: /\.html$/, 39 | loader: 'raw', 40 | exclude: root('src', 'index.html'), 41 | include: root('src', 'app') 42 | } 43 | ] 44 | }, 45 | plugins: [ 46 | new HtmlWebpackPlugin({ 47 | template: './src/index.html' 48 | }), 49 | new ExtractTextPlugin({filename: 'css/[name].[hash].css'}) 50 | ] 51 | }; 52 | 53 | // Helper functions 54 | function root(args) { 55 | args = Array.prototype.slice.call(arguments, 0); 56 | return path.join.apply(path, [__dirname].concat(args)); 57 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /typings 3 | /app/*.js 4 | /app/*.map 5 | /dist 6 | 7 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/app.component.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 1.2em; 3 | color: #999; 4 | margin-bottom: 0; 5 | } 6 | h2 { 7 | font-size: 2em; 8 | margin-top: 0; 9 | padding-top: 0; 10 | } 11 | nav a { 12 | padding: 5px 10px; 13 | text-decoration: none; 14 | margin-top: 10px; 15 | display: inline-block; 16 | background-color: #eee; 17 | border-radius: 4px; 18 | } 19 | nav a:visited, a:link { 20 | color: #607D8B; 21 | } 22 | nav a:hover { 23 | color: #039be5; 24 | background-color: #CFD8DC; 25 | } 26 | nav a.active { 27 | color: #039be5; 28 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | 4 | @Component({ 5 | moduleId: module.id, 6 | selector: 'my-app', 7 | template: ` 8 |

{{title}}

9 | 10 | 14 | 15 | `, 16 | styleUrls: ['app.component.css'] 17 | }) 18 | 19 | export class AppComponent { 20 | title = 'Tour of Heroes'; 21 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/app.module.ts: -------------------------------------------------------------------------------- 1 | import './rxjs-extensions' 2 | 3 | import {NgModule} from '@angular/core'; 4 | import {BrowserModule} from '@angular/platform-browser'; 5 | import {FormsModule} from '@angular/forms'; 6 | import {HttpModule} from '@angular/http'; 7 | 8 | import {InMemoryWebApiModule} from 'angular-in-memory-web-api/in-memory-web-api.module'; 9 | import { InMemoryDataService } from './in-memory-data.service'; 10 | 11 | import {AppComponent} from './app.component'; 12 | import {DashboardComponent} from './dashboard.component'; 13 | import {HeroDetailComponent} from './hero-detail.component'; 14 | import {HeroesComponent} from './heroes.component'; 15 | import {HeroService} from "./hero.service"; 16 | 17 | import {AppRoutingModule} from './app.routing.module'; 18 | 19 | import {HeroSearchComponent} from "./hero-search.component"; 20 | 21 | @NgModule({ 22 | imports: [ 23 | BrowserModule, 24 | FormsModule, 25 | HttpModule, 26 | InMemoryWebApiModule.forRoot(InMemoryDataService), 27 | AppRoutingModule 28 | ], 29 | declarations: [ 30 | AppComponent, 31 | DashboardComponent, 32 | HeroDetailComponent, 33 | HeroesComponent, 34 | HeroSearchComponent 35 | ], 36 | bootstrap: [AppComponent], 37 | providers: [HeroService] 38 | }) 39 | 40 | export class AppModule { 41 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/app.routing.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {RouterModule, Routes} from '@angular/router'; 3 | 4 | import {DashboardComponent} from './dashboard.component'; 5 | import {HeroesComponent} from './heroes.component'; 6 | import {HeroDetailComponent} from './hero-detail.component'; 7 | 8 | const routes: Routes = [ 9 | { path: '', redirectTo: '/dashboard', pathMatch: 'full'}, 10 | { path: 'dashboard', component: DashboardComponent}, 11 | { path: 'detail/:id', component: HeroDetailComponent}, 12 | { path: 'heroes', component: HeroesComponent }, 13 | ]; 14 | 15 | @NgModule({ 16 | imports: [RouterModule.forRoot(routes)], 17 | exports: [RouterModule] 18 | }) 19 | export class AppRoutingModule {} 20 | 21 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/dashboard.component.css: -------------------------------------------------------------------------------- 1 | [class*='col-'] { 2 | float: left; 3 | } 4 | *, *:after, *:before { 5 | -webkit-box-sizing: border-box; 6 | -moz-box-sizing: border-box; 7 | box-sizing: border-box; 8 | } 9 | h3 { 10 | text-align: center; margin-bottom: 0; 11 | } 12 | [class*='col-'] { 13 | padding-right: 20px; 14 | padding-bottom: 20px; 15 | } 16 | [class*='col-']:last-of-type { 17 | padding-right: 0; 18 | } 19 | .grid { 20 | margin: 0; 21 | } 22 | .col-1-4 { 23 | width: 25%; 24 | } 25 | .module { 26 | padding: 20px; 27 | text-align: center; 28 | color: #eee; 29 | max-height: 120px; 30 | min-width: 120px; 31 | background-color: #607D8B; 32 | border-radius: 2px; 33 | } 34 | h4 { 35 | position: relative; 36 | } 37 | .module:hover { 38 | background-color: #EEE; 39 | cursor: pointer; 40 | color: #607d8b; 41 | } 42 | .grid-pad { 43 | padding: 10px 0; 44 | } 45 | .grid-pad > [class*='col-']:last-of-type { 46 | padding-right: 20px; 47 | } 48 | @media (max-width: 600px) { 49 | .module { 50 | font-size: 10px; 51 | max-height: 75px; } 52 | } 53 | @media (max-width: 1024px) { 54 | .grid { 55 | margin: 0; 56 | } 57 | .module { 58 | min-width: 60px; 59 | } 60 | } 61 | 62 | 63 | /* 64 | Copyright 2016 Google Inc. All Rights Reserved. 65 | Use of this source code is governed by an MIT-style license that 66 | can be found in the LICENSE file at http://angular.io/license 67 | */ -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/dashboard.component.html: -------------------------------------------------------------------------------- 1 |

Top Heroes

2 |
3 |
5 |
6 |

{{hero.name}}

7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/dashboard.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Router} from '@angular/router'; 3 | 4 | import {Hero} from './hero'; 5 | import {HeroService} from "./hero.service"; 6 | 7 | @Component({ 8 | moduleId: module.id, 9 | selector: 'my-dashboard', 10 | templateUrl: 'dashboard.component.html', 11 | styleUrls: ['dashboard.component.css'] 12 | }) 13 | export class DashboardComponent implements OnInit { 14 | heroes:Hero[] = []; 15 | 16 | constructor( 17 | private router:Router, 18 | private heroService:HeroService) { 19 | } 20 | 21 | ngOnInit():void { 22 | this.heroService.getHeroes() 23 | .then(heroes => this.heroes = heroes.slice(1, 5)); 24 | } 25 | 26 | gotoDetail(hero:Hero): void { 27 | let link = ['/detail', hero.id]; 28 | this.router.navigate(link); 29 | } 30 | 31 | 32 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/hero-detail.component.css: -------------------------------------------------------------------------------- 1 | label { 2 | display: inline-block; 3 | width: 3em; 4 | margin: .5em 0; 5 | color: #607D8B; 6 | font-weight: bold; 7 | } 8 | input { 9 | height: 2em; 10 | font-size: 1em; 11 | padding-left: .4em; 12 | } 13 | button { 14 | margin-top: 20px; 15 | font-family: Arial; 16 | background-color: #eee; 17 | border: none; 18 | padding: 5px 10px; 19 | border-radius: 4px; 20 | cursor: pointer; cursor: hand; 21 | } 22 | button:hover { 23 | background-color: #cfd8dc; 24 | } 25 | button:disabled { 26 | background-color: #eee; 27 | color: #ccc; 28 | cursor: auto; 29 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/hero-detail.component.html: -------------------------------------------------------------------------------- 1 |
2 |

{{hero.name}} details!

3 |
{{hero.id}}
4 |
5 | 6 | 7 |
8 | 9 | 10 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/hero-detail.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {ActivatedRoute, Params} from '@angular/router'; 3 | import {Location} from '@angular/common'; 4 | import {HeroService} from './hero.service'; 5 | import {Hero} from "./hero"; 6 | 7 | @Component({ 8 | moduleId: module.id, 9 | selector: 'my-hero-detail', 10 | templateUrl: 'hero-detail.component.html', 11 | styleUrls: ['hero-detail.component.css'] 12 | }) 13 | 14 | export class HeroDetailComponent implements OnInit{ 15 | hero: Hero; 16 | 17 | ngOnInit():void { 18 | this.route.params.forEach((params: Params) => { 19 | let id = +params['id']; 20 | this.heroService.getHero(id) 21 | .then(hero => this.hero = hero); 22 | }); 23 | } 24 | constructor( 25 | private heroService: HeroService, 26 | private route: ActivatedRoute, 27 | private location: Location 28 | ) {} 29 | 30 | goBack(): void{ 31 | this.location.back(); 32 | } 33 | 34 | save(): void{ 35 | this.heroService.update(this.hero) 36 | .then(() => this.goBack()); 37 | } 38 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/hero-search.component.css: -------------------------------------------------------------------------------- 1 | .search-result{ 2 | border-bottom: 1px solid gray; 3 | border-left: 1px solid gray; 4 | border-right: 1px solid gray; 5 | width:195px; 6 | height: 20px; 7 | padding: 5px; 8 | background-color: white; 9 | cursor: pointer; 10 | } 11 | #search-box{ 12 | width: 200px; 13 | height: 20px; 14 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/hero-search.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Hero Search

3 | 5 | 6 |
7 |
10 | {{hero.name}} 11 |
12 |
13 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/hero-search.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Router} from '@angular/router'; 3 | import {Observable} from 'rxjs/observable'; 4 | import {Subject} from 'rxjs/subject'; 5 | 6 | import {HeroSearchService} from './hero-search.service'; 7 | import {Hero} from './hero'; 8 | 9 | @Component({ 10 | moduleId: module.id, 11 | selector: 'hero-search', 12 | templateUrl: 'hero-search.component.html', 13 | styleUrls: ['hero-search.component.css'], 14 | providers: [HeroSearchService] 15 | }) 16 | export class HeroSearchComponent implements OnInit { 17 | heroes: Observable; 18 | private searchTerms = new Subject(); 19 | 20 | constructor( 21 | private heroSearchService: HeroSearchService, 22 | private router: Router){} 23 | 24 | search(term: string): void{ 25 | this.searchTerms.next(term); 26 | } 27 | 28 | ngOnInit():void { 29 | this.heroes = this.searchTerms 30 | .debounceTime(300) 31 | .distinctUntilChanged() 32 | .switchMap(term => 33 | term ? this.heroSearchService.search(term) : Observable.of([])) 34 | .catch(error => { 35 | console.log(error); 36 | return Observable.of([]) 37 | }); 38 | } 39 | 40 | gotoDetail(hero: Hero): void{ 41 | let link = ['/detail', hero.id]; 42 | this.router.navigate(link); 43 | } 44 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/hero-search.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response } from '@angular/http'; 3 | 4 | import { Observable } from 'rxjs'; 5 | 6 | import { Hero } from './hero'; 7 | 8 | @Injectable() 9 | export class HeroSearchService{ 10 | constructor(private http: Http){} 11 | 12 | search(term: string): Observable { 13 | return this.http 14 | .get(`app/heroes/?name=${term}`) 15 | .map((r: Response) => r.json().data as Hero[]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/hero.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Headers, Http } from '@angular/http'; 3 | 4 | import 'rxjs/add/operator/toPromise'; 5 | 6 | import { Hero } from './hero'; 7 | 8 | @Injectable() 9 | export class HeroService{ 10 | 11 | private headers = new Headers({'Content-Type': 'application/json'}); 12 | private heroesUrl = 'app/heroes'; // URL to web api 13 | constructor(private http: Http) { } 14 | 15 | getHeroes(): Promise { 16 | return this.http.get(this.heroesUrl) 17 | .toPromise() 18 | .then(response => response.json().data as Hero[]) 19 | .catch(this.handleError); 20 | } 21 | 22 | getHeroesslowly(): Promise{ 23 | //delay 2000ms 24 | return new Promise(resolve => setTimeout(resolve, 2000)) 25 | .then(() => this.getHeroes()); 26 | } 27 | 28 | getHero(id: number): Promise { 29 | return this.getHeroes() 30 | .then(heroes => heroes.find(hero => hero.id === id)) 31 | 32 | } 33 | 34 | private handleError(error: any): Promise { 35 | console.error('An error occurred', error); // for demo purposes only 36 | return Promise.reject(error.message || error); 37 | } 38 | 39 | update(hero: Hero): Promise { 40 | const url = `${this.heroesUrl}/${hero.id}`; 41 | return this.http 42 | .put(url, JSON.stringify(hero), {headers: this.headers}) 43 | .toPromise() 44 | .then(() => hero) 45 | .catch(this.handleError); 46 | } 47 | 48 | create(name: string): Promise { 49 | return this.http 50 | .post(this.heroesUrl, 51 | JSON.stringify({name: name}), 52 | {headers: this.headers}) 53 | .toPromise() 54 | .then(res => res.json().data) 55 | .catch(this.handleError); 56 | } 57 | 58 | delete(id: number): Promise { 59 | const url = `${this.heroesUrl}/${id}`; 60 | return this.http.delete(url, {headers: this.headers}) 61 | .toPromise() 62 | .then(() => null) 63 | .catch(this.handleError); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/hero.ts: -------------------------------------------------------------------------------- 1 | export class Hero { 2 | id: number; 3 | name: string; 4 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/heroes.component.css: -------------------------------------------------------------------------------- 1 | .selected { 2 | background-color: #CFD8DC !important; 3 | color: white; 4 | } 5 | .heroes { 6 | margin: 0 0 2em 0; 7 | list-style-type: none; 8 | padding: 0; 9 | width: 15em; 10 | } 11 | .heroes li { 12 | cursor: pointer; 13 | position: relative; 14 | left: 0; 15 | background-color: #EEE; 16 | margin: .5em; 17 | padding: .3em 0; 18 | height: 1.6em; 19 | border-radius: 4px; 20 | } 21 | .heroes li.selected:hover { 22 | background-color: #BBD8DC !important; 23 | color: white; 24 | } 25 | .heroes li:hover { 26 | color: #607D8B; 27 | background-color: #DDD; 28 | left: .1em; 29 | } 30 | .heroes .text { 31 | position: relative; 32 | top: -3px; 33 | } 34 | .heroes .badge { 35 | display: inline-block; 36 | font-size: small; 37 | color: white; 38 | padding: 0.8em 0.7em 0 0.7em; 39 | background-color: #607D8B; 40 | line-height: 1em; 41 | position: relative; 42 | left: -1px; 43 | top: -4px; 44 | height: 1.8em; 45 | margin-right: .8em; 46 | border-radius: 4px 0 0 4px; 47 | } 48 | 49 | button.delete { 50 | float:right; 51 | margin-top: 2px; 52 | margin-right: .8em; 53 | background-color: gray !important; 54 | color:white; 55 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/heroes.component.html: -------------------------------------------------------------------------------- 1 |

My Heroes

2 |
3 | 4 | 5 |
6 |
    7 |
  • 9 | {{hero.id}} 10 | {{hero.name}} 11 | 13 |
  • 14 | 15 | 16 |
    17 |

    18 | {{selectedHero.name | uppercase}} is my hero 19 |

    20 | 21 |
    22 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/heroes.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {Hero} from "./hero"; 3 | import {HEROES} from "./mock-hero"; 4 | import {HeroService} from "./hero.service"; 5 | import {OnInit} from '@angular/core' 6 | 7 | import {Router} from '@angular/router'; 8 | 9 | @Component({ 10 | moduleId: module.id, 11 | selector: 'my-heroes', 12 | templateUrl: 'heroes.component.html', 13 | styleUrls: ['heroes.component.css'] 14 | }) 15 | 16 | export class HeroesComponent implements OnInit { 17 | heroes:Hero[]; 18 | selectedHero:Hero; 19 | 20 | constructor(private router:Router, 21 | private heroService:HeroService) { 22 | } 23 | 24 | getHeroes():void { 25 | this.heroService.getHeroes() 26 | //this.heroService.getHeroesslowly() 27 | .then(heroes => this.heroes = heroes); 28 | } 29 | 30 | ngOnInit():void { 31 | this.getHeroes(); 32 | } 33 | 34 | onSelect(hero:Hero):void { 35 | this.selectedHero = hero; 36 | } 37 | 38 | gotoDetail():void { 39 | this.router.navigate(['/detail', this.selectedHero.id]); 40 | } 41 | 42 | add(name:string):void { 43 | name = name.trim(); 44 | if (!name) { 45 | return; 46 | } 47 | this.heroService.create(name) 48 | .then(hero => { 49 | this.heroes.push(hero); 50 | this.selectedHero = null; 51 | }); 52 | } 53 | 54 | delete(hero: Hero): void { 55 | this.heroService 56 | .delete(hero.id) 57 | .then(() => { 58 | this.heroes = this.heroes.filter(h => h != hero); 59 | if(this.selectedHero === hero){ 60 | this.selectedHero = null; 61 | } 62 | }) 63 | } 64 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/in-memory-data.service.ts: -------------------------------------------------------------------------------- 1 | import {InMemoryDbService} from 'angular-in-memory-web-api'; 2 | 3 | export class InMemoryDataService implements InMemoryDbService { 4 | createDb() { 5 | let heroes = [ 6 | {id: 11, name: 'Mr. Nice'}, 7 | {id: 12, name: 'Narco'}, 8 | {id: 13, name: 'Bombasto'}, 9 | {id: 14, name: 'Celeritas'}, 10 | {id: 15, name: 'Magneta'}, 11 | {id: 16, name: 'RubberMan'}, 12 | {id: 17, name: 'Dynama'}, 13 | {id: 18, name: 'Dr IQ'}, 14 | {id: 19, name: 'Magma'}, 15 | {id: 20, name: 'Tornado'} 16 | ]; 17 | return {heroes}; 18 | } 19 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/main.ts: -------------------------------------------------------------------------------- 1 | import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; 2 | 3 | import {AppModule} from './app.module' ; 4 | 5 | const platform = platformBrowserDynamic(); 6 | platform.bootstrapModule(AppModule); 7 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/mock-hero.ts: -------------------------------------------------------------------------------- 1 | import {Hero} from './hero' 2 | 3 | export const HEROES:Hero[] = [ 4 | {id: 11, name: 'Mr. Nice'}, 5 | {id: 12, name: 'Narco'}, 6 | {id: 13, name: 'Bombasto'}, 7 | {id: 14, name: 'Celeritas'}, 8 | {id: 15, name: 'Magneta'}, 9 | {id: 16, name: 'RubberMan'}, 10 | {id: 17, name: 'Dynama'}, 11 | {id: 18, name: 'Dr IQ'}, 12 | {id: 19, name: 'Magma'}, 13 | {id: 20, name: 'Tornado'} 14 | ]; 15 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/app.back/rxjs-extensions.ts: -------------------------------------------------------------------------------- 1 | // Observable class extensions 2 | import 'rxjs/add/observable/of'; 3 | import 'rxjs/add/observable/throw'; 4 | 5 | // Observable operators 6 | import 'rxjs/add/operator/catch'; 7 | import 'rxjs/add/operator/debounceTime'; 8 | import 'rxjs/add/operator/distinctUntilChanged'; 9 | import 'rxjs/add/operator/do'; 10 | import 'rxjs/add/operator/filter'; 11 | import 'rxjs/add/operator/map'; 12 | import 'rxjs/add/operator/switchMap'; -------------------------------------------------------------------------------- /ng2-tour-of-heroes/copyfile.sh.back: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | cp ./app/*.css ./app/*.html ./dist/ 4 | 5 | 6 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/index.html.back: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular2 Heroes 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Loading... 22 | 23 | 24 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-tour-of-heroes", 3 | "version": "2.0.0", 4 | "scripts": { 5 | "build": "webpack --progress", 6 | "build:prod": "webpack -p --progress", 7 | "postinstall": "typings install", 8 | "serve": "webpack-dev-server --inline --progress" 9 | }, 10 | "license": "ISC", 11 | "dependencies": { 12 | "@angular/common": "2.4.2", 13 | "@angular/compiler": "2.4.2", 14 | "@angular/core": "2.4.2", 15 | "@angular/forms": "2.4.2", 16 | "@angular/http": "2.4.2", 17 | "@angular/platform-browser": "2.4.2", 18 | "@angular/platform-browser-dynamic": "2.4.2", 19 | "@angular/router": "3.4.2", 20 | "angular-in-memory-web-api": "0.2.4", 21 | "bootstrap": "3.3.7", 22 | "core-js": "2.4.1", 23 | "reflect-metadata": "0.1.9", 24 | "rxjs": "5.0.3", 25 | "zone.js": "0.7.4" 26 | }, 27 | "devDependencies": { 28 | "angular2-template-loader": "0.5.0", 29 | "awesome-typescript-loader": "2.2.4", 30 | "css-loader": "0.23.1", 31 | "extract-text-webpack-plugin": "1.0.1", 32 | "html-loader": "0.4.4", 33 | "html-webpack-plugin": "2.22.0", 34 | "raw-loader": "0.5.1", 35 | "style-loader": "0.13.1", 36 | "ts-loader": "1.3.0", 37 | "typescript": "2.0.10", 38 | "typings": "2.1.0", 39 | "webpack": "1.14.0", 40 | "webpack-dev-server": "1.16.2" 41 | } 42 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/package.json.bak: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-tour-of-heroes", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "start": "npm run cleandist && npm run moveassets && tsc && concurrently \"tsc -w\" \"lite-server\" ", 6 | "lite": "lite-server", 7 | "postinstall": "typings install", 8 | "tsc": "tsc", 9 | "tsc:w": "tsc -w", 10 | "typings": "typings", 11 | "cleandist": "rm -rf dist/*", 12 | "moveassets": "rsync -a --include='*.css' --include='*.html' --include='*/' --exclude='*' app/ dist/" 13 | }, 14 | "license": "ISC", 15 | "dependencies": { 16 | "@angular/common": "~2.0.1", 17 | "@angular/compiler": "~2.0.1", 18 | "@angular/core": "~2.0.1", 19 | "@angular/forms": "~2.0.1", 20 | "@angular/http": "~2.0.1", 21 | "@angular/platform-browser": "~2.0.1", 22 | "@angular/platform-browser-dynamic": "~2.0.1", 23 | "@angular/router": "~3.0.1", 24 | "@angular/upgrade": "~2.0.1", 25 | "angular-in-memory-web-api": "~0.1.1", 26 | "bootstrap": "^3.3.7", 27 | "core-js": "^2.4.1", 28 | "reflect-metadata": "^0.1.8", 29 | "rxjs": "5.0.0-beta.12", 30 | "systemjs": "0.19.39", 31 | "zone.js": "^0.6.25" 32 | }, 33 | "devDependencies": { 34 | "concurrently": "^3.0.0", 35 | "lite-server": "^2.2.2", 36 | "typescript": "^2.0.3", 37 | "typings":"^1.4.0", 38 | "onchange":"^3.0.2" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/app.component.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 1.2em; 3 | color: #999; 4 | margin-bottom: 0; 5 | } 6 | h2 { 7 | font-size: 2em; 8 | margin-top: 0; 9 | padding-top: 0; 10 | } 11 | nav a { 12 | padding: 5px 10px; 13 | text-decoration: none; 14 | margin-top: 10px; 15 | display: inline-block; 16 | background-color: #eee; 17 | border-radius: 4px; 18 | } 19 | nav a:visited, a:link { 20 | color: #607D8B; 21 | } 22 | nav a:hover { 23 | color: #039be5; 24 | background-color: #CFD8DC; 25 | } 26 | nav a.active { 27 | color: #039be5; 28 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | 4 | @Component({ 5 | selector: 'my-app', 6 | template: ` 7 |

{{title}}

8 | 9 | 13 | 14 | `, 15 | styleUrls: ['./app.component.css'] 16 | }) 17 | 18 | export class AppComponent { 19 | title = 'Tour of Heroes'; 20 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import '../rxjs-extensions' 2 | 3 | import {NgModule} from '@angular/core'; 4 | import {BrowserModule} from '@angular/platform-browser'; 5 | import {FormsModule} from '@angular/forms'; 6 | import {HttpModule} from '@angular/http'; 7 | 8 | import { InMemoryWebApiModule } from 'angular-in-memory-web-api/in-memory-web-api.module'; 9 | import { InMemoryDataService } from './hero/in-memory-data.service'; 10 | 11 | import {AppComponent} from './app.component'; 12 | import {DashboardComponent} from './dashboard/dashboard.component'; 13 | import {HeroDetailComponent} from './hero-detail/hero-detail.component'; 14 | import {HeroesComponent} from './heroes/heroes.component'; 15 | import {HeroService} from "./hero/hero.service"; 16 | 17 | import {AppRoutingModule} from './app.routing.module'; 18 | 19 | import {HeroSearchComponent} from "./hero-search/hero-search.component"; 20 | 21 | @NgModule({ 22 | imports: [ 23 | BrowserModule, 24 | FormsModule, 25 | HttpModule, 26 | InMemoryWebApiModule.forRoot(InMemoryDataService), 27 | AppRoutingModule 28 | ], 29 | declarations: [ 30 | AppComponent, 31 | DashboardComponent, 32 | HeroDetailComponent, 33 | HeroesComponent, 34 | HeroSearchComponent 35 | ], 36 | bootstrap: [AppComponent], 37 | providers: [HeroService] 38 | }) 39 | 40 | export class AppModule { 41 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/app.routing.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {RouterModule, Routes} from '@angular/router'; 3 | 4 | import {DashboardComponent} from './dashboard/dashboard.component'; 5 | import {HeroesComponent} from './heroes/heroes.component'; 6 | import {HeroDetailComponent} from './hero-detail/hero-detail.component'; 7 | 8 | const routes: Routes = [ 9 | { path: '', redirectTo: '/dashboard', pathMatch: 'full'}, 10 | { path: 'dashboard', component: DashboardComponent}, 11 | { path: 'detail/:id', component: HeroDetailComponent}, 12 | { path: 'heroes', component: HeroesComponent }, 13 | ]; 14 | 15 | @NgModule({ 16 | imports: [RouterModule.forRoot(routes)], 17 | exports: [RouterModule] 18 | }) 19 | export class AppRoutingModule {} 20 | 21 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/dashboard/dashboard.component.css: -------------------------------------------------------------------------------- 1 | [class*='col-'] { 2 | float: left; 3 | } 4 | *, *:after, *:before { 5 | -webkit-box-sizing: border-box; 6 | -moz-box-sizing: border-box; 7 | box-sizing: border-box; 8 | } 9 | h3 { 10 | text-align: center; margin-bottom: 0; 11 | } 12 | [class*='col-'] { 13 | padding-right: 20px; 14 | padding-bottom: 20px; 15 | } 16 | [class*='col-']:last-of-type { 17 | padding-right: 0; 18 | } 19 | .grid { 20 | margin: 0; 21 | } 22 | .col-1-4 { 23 | width: 25%; 24 | } 25 | .module { 26 | padding: 20px; 27 | text-align: center; 28 | color: #eee; 29 | max-height: 120px; 30 | min-width: 120px; 31 | background-color: #607D8B; 32 | border-radius: 2px; 33 | } 34 | h4 { 35 | position: relative; 36 | } 37 | .module:hover { 38 | background-color: #EEE; 39 | cursor: pointer; 40 | color: #607d8b; 41 | } 42 | .grid-pad { 43 | padding: 10px 0; 44 | } 45 | .grid-pad > [class*='col-']:last-of-type { 46 | padding-right: 20px; 47 | } 48 | @media (max-width: 600px) { 49 | .module { 50 | font-size: 10px; 51 | max-height: 75px; } 52 | } 53 | @media (max-width: 1024px) { 54 | .grid { 55 | margin: 0; 56 | } 57 | .module { 58 | min-width: 60px; 59 | } 60 | } 61 | 62 | 63 | /* 64 | Copyright 2016 Google Inc. All Rights Reserved. 65 | Use of this source code is governed by an MIT-style license that 66 | can be found in the LICENSE file at http://angular.io/license 67 | */ -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/dashboard/dashboard.component.html: -------------------------------------------------------------------------------- 1 |

Top Heroes

2 |
3 |
5 |
6 |

{{hero.name}}

7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/dashboard/dashboard.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Router} from '@angular/router'; 3 | 4 | import {Hero} from '../hero/hero'; 5 | import {HeroService} from "../hero/hero.service"; 6 | 7 | @Component({ 8 | selector: 'my-dashboard', 9 | templateUrl: './dashboard.component.html', 10 | styleUrls: ['./dashboard.component.css'] 11 | }) 12 | export class DashboardComponent implements OnInit { 13 | heroes:Hero[] = []; 14 | 15 | constructor( 16 | private router:Router, 17 | private heroService:HeroService) { 18 | } 19 | 20 | ngOnInit():void { 21 | this.heroService.getHeroes() 22 | .then(heroes => this.heroes = heroes.slice(1, 5)); 23 | } 24 | 25 | gotoDetail(hero:Hero): void { 26 | let link = ['/detail', hero.id]; 27 | this.router.navigate(link); 28 | } 29 | 30 | 31 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/hero-detail/hero-detail.component.css: -------------------------------------------------------------------------------- 1 | label { 2 | display: inline-block; 3 | width: 3em; 4 | margin: .5em 0; 5 | color: #607D8B; 6 | font-weight: bold; 7 | } 8 | input { 9 | height: 2em; 10 | font-size: 1em; 11 | padding-left: .4em; 12 | } 13 | button { 14 | margin-top: 20px; 15 | font-family: Arial; 16 | background-color: #eee; 17 | border: none; 18 | padding: 5px 10px; 19 | border-radius: 4px; 20 | cursor: pointer; cursor: hand; 21 | } 22 | button:hover { 23 | background-color: #cfd8dc; 24 | } 25 | button:disabled { 26 | background-color: #eee; 27 | color: #ccc; 28 | cursor: auto; 29 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/hero-detail/hero-detail.component.html: -------------------------------------------------------------------------------- 1 |
2 |

{{hero.name}} details!

3 |
{{hero.id}}
4 |
5 | 6 | 7 |
8 | 9 | 10 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/hero-detail/hero-detail.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {ActivatedRoute, Params} from '@angular/router'; 3 | import {Location} from '@angular/common'; 4 | import {HeroService} from '../hero/hero.service'; 5 | import {Hero} from "../hero/hero"; 6 | 7 | @Component({ 8 | selector: 'my-hero-detail', 9 | templateUrl: './hero-detail.component.html', 10 | styleUrls: ['./hero-detail.component.css'] 11 | }) 12 | 13 | export class HeroDetailComponent implements OnInit{ 14 | hero: Hero; 15 | 16 | ngOnInit():void { 17 | this.route.params.forEach((params: Params) => { 18 | let id = +params['id']; 19 | this.heroService.getHero(id) 20 | .then(hero => this.hero = hero); 21 | }); 22 | } 23 | constructor( 24 | private heroService: HeroService, 25 | private route: ActivatedRoute, 26 | private location: Location 27 | ) {} 28 | 29 | goBack(): void{ 30 | this.location.back(); 31 | } 32 | 33 | save(): void{ 34 | this.heroService.update(this.hero) 35 | .then(() => this.goBack()); 36 | } 37 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/hero-search/hero-search.component.css: -------------------------------------------------------------------------------- 1 | .search-result{ 2 | border-bottom: 1px solid gray; 3 | border-left: 1px solid gray; 4 | border-right: 1px solid gray; 5 | width:195px; 6 | height: 20px; 7 | padding: 5px; 8 | background-color: white; 9 | cursor: pointer; 10 | } 11 | #search-box{ 12 | width: 200px; 13 | height: 20px; 14 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/hero-search/hero-search.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Hero Search

3 | 5 | 6 |
7 |
10 | {{hero.name}} 11 |
12 |
13 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/hero-search/hero-search.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Router} from '@angular/router'; 3 | import {Observable} from 'rxjs/observable'; 4 | import {Subject} from 'rxjs/subject'; 5 | 6 | import {HeroSearchService} from './hero-search.service'; 7 | import {Hero} from '../hero/hero'; 8 | 9 | @Component({ 10 | selector: 'hero-search', 11 | templateUrl: './hero-search.component.html', 12 | styleUrls: ['./hero-search.component.css'], 13 | providers: [HeroSearchService] 14 | }) 15 | export class HeroSearchComponent implements OnInit { 16 | heroes: Observable; 17 | private searchTerms = new Subject(); 18 | 19 | constructor( 20 | private heroSearchService: HeroSearchService, 21 | private router: Router){} 22 | 23 | search(term: string): void{ 24 | this.searchTerms.next(term); 25 | } 26 | 27 | ngOnInit():void { 28 | this.heroes = this.searchTerms 29 | .debounceTime(300) 30 | .distinctUntilChanged() 31 | .switchMap(term => 32 | term ? this.heroSearchService.search(term) : Observable.of([])) 33 | .catch(error => { 34 | console.log(error); 35 | return Observable.of([]) 36 | }); 37 | } 38 | 39 | gotoDetail(hero: Hero): void{ 40 | let link = ['/detail', hero.id]; 41 | this.router.navigate(link); 42 | } 43 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/hero-search/hero-search.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response } from '@angular/http'; 3 | 4 | import { Observable } from 'rxjs'; 5 | 6 | import { Hero } from '../hero/hero'; 7 | 8 | @Injectable() 9 | export class HeroSearchService{ 10 | constructor(private http: Http){} 11 | 12 | search(term: string): Observable { 13 | return this.http 14 | .get(`app/heroes/?name=${term}`) 15 | .map((r: Response) => r.json().data as Hero[]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/hero/hero.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Headers, Http } from '@angular/http'; 3 | 4 | import 'rxjs/add/operator/toPromise'; 5 | 6 | import { Hero } from './hero'; 7 | 8 | @Injectable() 9 | export class HeroService{ 10 | 11 | private headers = new Headers({'Content-Type': 'application/json'}); 12 | private heroesUrl = 'app/heroes'; // URL to web api 13 | constructor(private http: Http) { } 14 | 15 | getHeroes(): Promise { 16 | return this.http.get(this.heroesUrl) 17 | .toPromise() 18 | .then(response => response.json().data as Hero[]) 19 | .catch(this.handleError); 20 | } 21 | 22 | getHeroesslowly(): Promise{ 23 | //delay 2000ms 24 | return new Promise(resolve => setTimeout(resolve, 2000)) 25 | .then(() => this.getHeroes()); 26 | } 27 | 28 | getHero(id: number): Promise { 29 | return this.getHeroes() 30 | .then(heroes => heroes.find(hero => hero.id === id)) 31 | 32 | } 33 | 34 | private handleError(error: any): Promise { 35 | console.error('An error occurred', error); // for demo purposes only 36 | return Promise.reject(error.message || error); 37 | } 38 | 39 | update(hero: Hero): Promise { 40 | const url = `${this.heroesUrl}/${hero.id}`; 41 | return this.http 42 | .put(url, JSON.stringify(hero), {headers: this.headers}) 43 | .toPromise() 44 | .then(() => hero) 45 | .catch(this.handleError); 46 | } 47 | 48 | create(name: string): Promise { 49 | return this.http 50 | .post(this.heroesUrl, 51 | JSON.stringify({name: name}), 52 | {headers: this.headers}) 53 | .toPromise() 54 | .then(res => res.json().data) 55 | .catch(this.handleError); 56 | } 57 | 58 | delete(id: number): Promise { 59 | const url = `${this.heroesUrl}/${id}`; 60 | return this.http.delete(url, {headers: this.headers}) 61 | .toPromise() 62 | .then(() => null) 63 | .catch(this.handleError); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/hero/hero.ts: -------------------------------------------------------------------------------- 1 | export class Hero { 2 | id: number; 3 | name: string; 4 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/hero/in-memory-data.service.ts: -------------------------------------------------------------------------------- 1 | import {InMemoryDbService} from 'angular-in-memory-web-api'; 2 | 3 | export class InMemoryDataService implements InMemoryDbService { 4 | createDb() { 5 | let heroes = [ 6 | {id: 11, name: 'Mr. Nice'}, 7 | {id: 12, name: 'Narco'}, 8 | {id: 13, name: 'Bombasto'}, 9 | {id: 14, name: 'Celeritas'}, 10 | {id: 15, name: 'Magneta'}, 11 | {id: 16, name: 'RubberMan'}, 12 | {id: 17, name: 'Dynama'}, 13 | {id: 18, name: 'Dr IQ'}, 14 | {id: 19, name: 'Magma'}, 15 | {id: 20, name: 'Tornado'} 16 | ]; 17 | return {heroes}; 18 | } 19 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/hero/mock-hero.ts: -------------------------------------------------------------------------------- 1 | import {Hero} from './hero' 2 | 3 | export const HEROES:Hero[] = [ 4 | {id: 11, name: 'Mr. Nice'}, 5 | {id: 12, name: 'Narco'}, 6 | {id: 13, name: 'Bombasto'}, 7 | {id: 14, name: 'Celeritas'}, 8 | {id: 15, name: 'Magneta'}, 9 | {id: 16, name: 'RubberMan'}, 10 | {id: 17, name: 'Dynama'}, 11 | {id: 18, name: 'Dr IQ'}, 12 | {id: 19, name: 'Magma'}, 13 | {id: 20, name: 'Tornado'} 14 | ]; 15 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/heroes/heroes.component.css: -------------------------------------------------------------------------------- 1 | .selected { 2 | background-color: #CFD8DC !important; 3 | color: white; 4 | } 5 | .heroes { 6 | margin: 0 0 2em 0; 7 | list-style-type: none; 8 | padding: 0; 9 | width: 15em; 10 | } 11 | .heroes li { 12 | cursor: pointer; 13 | position: relative; 14 | left: 0; 15 | background-color: #EEE; 16 | margin: .5em; 17 | padding: .3em 0; 18 | height: 1.6em; 19 | border-radius: 4px; 20 | } 21 | .heroes li.selected:hover { 22 | background-color: #BBD8DC !important; 23 | color: white; 24 | } 25 | .heroes li:hover { 26 | color: #607D8B; 27 | background-color: #DDD; 28 | left: .1em; 29 | } 30 | .heroes .text { 31 | position: relative; 32 | top: -3px; 33 | } 34 | .heroes .badge { 35 | display: inline-block; 36 | font-size: small; 37 | color: white; 38 | padding: 0.8em 0.7em 0 0.7em; 39 | background-color: #607D8B; 40 | line-height: 1em; 41 | position: relative; 42 | left: -1px; 43 | top: -4px; 44 | height: 1.8em; 45 | margin-right: .8em; 46 | border-radius: 4px 0 0 4px; 47 | } 48 | 49 | button.delete { 50 | float:right; 51 | margin-top: 2px; 52 | margin-right: .8em; 53 | background-color: gray !important; 54 | color:white; 55 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/heroes/heroes.component.html: -------------------------------------------------------------------------------- 1 |

My Heroes

2 |
3 | 4 | 5 |
6 |
    7 |
  • 9 | {{hero.id}} 10 | {{hero.name}} 11 | 13 |
  • 14 | 15 | 16 |
    17 |

    18 | {{selectedHero.name | uppercase}} is my hero 19 |

    20 | 21 |
    22 |
-------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/app/heroes/heroes.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {Hero} from "../hero/hero"; 3 | import {HEROES} from "../hero/mock-hero"; 4 | import {HeroService} from "../hero/hero.service"; 5 | import {OnInit} from '@angular/core' 6 | 7 | import {Router} from '@angular/router'; 8 | 9 | @Component({ 10 | selector: 'my-heroes', 11 | templateUrl: './heroes.component.html', 12 | styleUrls: ['./heroes.component.css'] 13 | }) 14 | 15 | export class HeroesComponent implements OnInit { 16 | heroes:Hero[]; 17 | selectedHero:Hero; 18 | 19 | constructor(private router:Router, 20 | private heroService:HeroService) { 21 | } 22 | 23 | getHeroes():void { 24 | this.heroService.getHeroes() 25 | //this.heroService.getHeroesslowly() 26 | .then(heroes => this.heroes = heroes); 27 | } 28 | 29 | ngOnInit():void { 30 | this.getHeroes(); 31 | } 32 | 33 | onSelect(hero:Hero):void { 34 | this.selectedHero = hero; 35 | } 36 | 37 | gotoDetail():void { 38 | this.router.navigate(['/detail', this.selectedHero.id]); 39 | } 40 | 41 | add(name:string):void { 42 | name = name.trim(); 43 | if (!name) { 44 | return; 45 | } 46 | this.heroService.create(name) 47 | .then(hero => { 48 | this.heroes.push(hero); 49 | this.selectedHero = null; 50 | }); 51 | } 52 | 53 | delete(hero: Hero): void { 54 | this.heroService 55 | .delete(hero.id) 56 | .then(() => { 57 | this.heroes = this.heroes.filter(h => h != hero); 58 | if(this.selectedHero === hero){ 59 | this.selectedHero = null; 60 | } 61 | }) 62 | } 63 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular2 QuickStart 6 | 7 | 8 | 9 | 10 | 11 | 12 | Loading... 13 | 14 | 15 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/main.ts: -------------------------------------------------------------------------------- 1 | import 'core-js'; 2 | import 'reflect-metadata'; 3 | import 'zone.js/dist/zone'; 4 | 5 | import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; 6 | import {AppModule} from './app/app.module' ; 7 | 8 | const platform = platformBrowserDynamic(); 9 | platform.bootstrapModule(AppModule); 10 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/rxjs-extensions.ts: -------------------------------------------------------------------------------- 1 | // Observable class extensions 2 | import 'rxjs/add/observable/of'; 3 | import 'rxjs/add/observable/throw'; 4 | 5 | // Observable operators 6 | import 'rxjs/add/operator/catch'; 7 | import 'rxjs/add/operator/debounceTime'; 8 | import 'rxjs/add/operator/distinctUntilChanged'; 9 | import 'rxjs/add/operator/do'; 10 | import 'rxjs/add/operator/filter'; 11 | import 'rxjs/add/operator/map'; 12 | import 'rxjs/add/operator/switchMap'; -------------------------------------------------------------------------------- /ng2-tour-of-heroes/src/styles.css: -------------------------------------------------------------------------------- 1 | /* Master Styles */ 2 | h1 { 3 | color: #369; 4 | font-family: Arial, Helvetica, sans-serif; 5 | font-size: 250%; 6 | } 7 | h2, h3 { 8 | color: #444; 9 | font-family: Arial, Helvetica, sans-serif; 10 | font-weight: lighter; 11 | } 12 | body { 13 | margin: 2em; 14 | } 15 | body, input[text], button { 16 | color: #888; 17 | font-family: Cambria, Georgia; 18 | } 19 | /* . . . */ 20 | /* everywhere else */ 21 | * { 22 | font-family: Arial, Helvetica, sans-serif; 23 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/styles.css.back: -------------------------------------------------------------------------------- 1 | /* Master Styles */ 2 | h1 { 3 | color: #369; 4 | font-family: Arial, Helvetica, sans-serif; 5 | font-size: 250%; 6 | } 7 | h2, h3 { 8 | color: #444; 9 | font-family: Arial, Helvetica, sans-serif; 10 | font-weight: lighter; 11 | } 12 | body { 13 | margin: 2em; 14 | } 15 | body, input[text], button { 16 | color: #888; 17 | font-family: Cambria, Georgia; 18 | } 19 | /* . . . */ 20 | /* everywhere else */ 21 | * { 22 | font-family: Arial, Helvetica, sans-serif; 23 | } -------------------------------------------------------------------------------- /ng2-tour-of-heroes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": false, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": false, 10 | "noImplicitAny": false 11 | }, 12 | "exclude": [ 13 | "node_modules" 14 | ] 15 | 16 | } 17 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "globalDependencies": { 3 | "core-js": "registry:dt/core-js#0.0.0+20160725163759", 4 | "jasmine": "registry:dt/jasmine#2.2.0+20160621224255", 5 | "node": "registry:dt/node#6.0.0+20160909174046" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ng2-tour-of-heroes/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | 4 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 6 | 7 | module.exports = { 8 | 9 | entry: './src/main.ts', 10 | output: { 11 | path: root('dist'), 12 | filename: 'app.bundle.js' 13 | }, 14 | resolve: { 15 | extensions: ['', '.js', '.ts', 'html', 'css'] 16 | }, 17 | module: { 18 | loaders: [{ 19 | test: /\.ts$/, 20 | loaders: ['awesome-typescript-loader', 'angular2-template-loader'] 21 | }, 22 | { 23 | test: /\.css$/, 24 | exclude: root('src', 'app'), 25 | loader: ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: ['css'] }) 26 | }, 27 | 28 | // all css required in src/app files will be merged in js files 29 | { 30 | test: /\.css$/, 31 | include: root('src', 'app'), 32 | loader: 'raw' 33 | }, 34 | 35 | // support for .html as raw text 36 | { 37 | test: /\.html$/, 38 | loader: 'raw', 39 | exclude: root('src', 'index.html'), 40 | include: root('src', 'app') 41 | } 42 | ] 43 | }, 44 | plugins: [ 45 | new HtmlWebpackPlugin({ 46 | template: './src/index.html' 47 | }), 48 | new ExtractTextPlugin({ filename: 'css/[name].css' }) 49 | ] 50 | }; 51 | 52 | // Helper functions 53 | function root(args) { 54 | args = Array.prototype.slice.call(arguments, 0); 55 | return path.join.apply(path, [__dirname].concat(args)); 56 | } -------------------------------------------------------------------------------- /typescript-demo/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /typings 3 | /*.js 4 | /build/ 5 | 6 | -------------------------------------------------------------------------------- /typescript-demo/TsClass.ts: -------------------------------------------------------------------------------- 1 | //类 2 | 3 | //class Animal { 4 | // name:string; 5 | // 6 | // constructor(theName:string) { 7 | // this.name = theName; 8 | // } 9 | // 10 | // move(distanceInMeters:number = 0) { 11 | // console.log(`${this.name} moved ${distanceInMeters}m.`); 12 | // } 13 | //} 14 | // 15 | //class Snake extends Animal { 16 | // constructor(name:string) { 17 | // super(name); 18 | // } 19 | // 20 | // //move(distanceInMeters = 5) { 21 | // // console.log("Slithering..."); 22 | // // super.move(distanceInMeters); 23 | // //} 24 | //} 25 | // 26 | //class Horse extends Animal { 27 | // constructor(name:string) { 28 | // super(name); 29 | // } 30 | // 31 | // move(distanceInMeters = 45) { 32 | // console.log("Galloping..."); 33 | // super.move(distanceInMeters); 34 | // } 35 | //} 36 | // 37 | //let sam = new Snake("Sammy the Python"); 38 | //let tom: Animal = new Horse("Tommy the Palomino"); 39 | // 40 | //sam.move(); 41 | //tom.move(34); 42 | 43 | //理解private 44 | //class Animal { 45 | // private name: string; 46 | // constructor(theName: string) { this.name = theName; } 47 | //} 48 | // 49 | //class Rhino extends Animal { 50 | // constructor() { super("Rhino"); } 51 | //} 52 | // 53 | //class Employee { 54 | // private name: string; 55 | // constructor(theName: string) { this.name = theName; } 56 | //} 57 | // 58 | //let animal = new Animal("Goat"); 59 | //let rhino = new Rhino(); 60 | //let employee = new Employee("Bob"); 61 | // 62 | //animal = rhino; 63 | ////animal = employee; // Error: Animal and Employee are not compatible 64 | 65 | 66 | //存取器 67 | //v0.1 68 | //class Employee { 69 | // fullName: string; 70 | //} 71 | // 72 | //let employee = new Employee(); 73 | //employee.fullName = "bob smith"; 74 | //if(employee.fullName) { 75 | // console.log(employee.fullName); 76 | //} 77 | 78 | //v0.2 79 | let passcode = "secret passcode"; 80 | 81 | class Employee { 82 | private _fullName: string; 83 | 84 | get fullName(): string { 85 | return this._fullName; 86 | } 87 | 88 | set fullName(newName: string) { 89 | if (passcode && passcode == "secret passcode") { 90 | this._fullName = newName; 91 | } 92 | else { 93 | console.log("Error: Unauthorized update of employee!"); 94 | } 95 | } 96 | } 97 | 98 | let employee = new Employee(); 99 | employee.fullName = "Bob smith"; 100 | if (employee.fullName) { 101 | alert(employee.fullName); 102 | } 103 | -------------------------------------------------------------------------------- /typescript-demo/TsInterface.ts: -------------------------------------------------------------------------------- 1 | //v0.1 2 | //function printLabel(labelObj: {label: string}){ 3 | // console.log(labelObj.label); 4 | //} 5 | // 6 | //let myObj = {size: 10, size1: 20, label: "size 10 Object"}; 7 | //printLabel(myObj); 8 | 9 | //v0.2 10 | //interface LabeledValue { 11 | // label: string; 12 | // 13 | //} 14 | // 15 | //function printLabel(labelObj: LabeledValue) { 16 | // console.log(labelObj.label); 17 | //} 18 | // 19 | //let myObj = {size: 10, label: "size 10 object"}; 20 | //printLabel(myObj); 21 | 22 | //可选属性 23 | //interface SquareConfig { 24 | // color?: string; 25 | // width?: number; 26 | //} 27 | // 28 | //function createSquare(config: SquareConfig): 29 | // {color: string, area: number} { 30 | // 31 | // let newSquare = {color: "white", area: 100}; 32 | // if(config.color) { 33 | // newSquare.color = config.color; 34 | // } 35 | // if(config.width) { 36 | // newSquare.area = config.width * config.width; 37 | // } 38 | // console.log(newSquare); 39 | // return newSquare; 40 | //} 41 | // 42 | //let mySquare = createSquare({color: "black"}); 43 | 44 | 45 | //只读属性 46 | //interface Point { 47 | // readonly x: number; 48 | // readonly y: number; 49 | //} 50 | // 51 | //let p1: Point = {x: 10, y: 20}; 52 | //console.log(p1); 53 | // 54 | //let a: number[] = [1,2,3,4]; 55 | //let ro: ReadonlyArray = a; 56 | //a = ro as number[]; 57 | //console.log(a); 58 | 59 | //函数类型 60 | //interface SearchFunc { 61 | // (source: string, subString: string): boolean; 62 | //} 63 | // 64 | //let mySearch: SearchFunc; 65 | //mySearch = function(src: string, sub: string):boolean { 66 | // let result = src.search(sub); 67 | // if(result == -1) { 68 | // return false; 69 | // }else { 70 | // return true; 71 | // } 72 | //} 73 | // 74 | //console.log(mySearch("tanhq", "tan")); 75 | // 76 | 77 | //可索引的类型 ?? 78 | 79 | //类类型 80 | interface ClockInterface { 81 | tick(); 82 | } 83 | 84 | interface ClockConstructor { 85 | new (hour:number, minute:number): ClockInterface; 86 | } 87 | 88 | function createClock(ctor:ClockConstructor, hour:number, minute:number):ClockInterface { 89 | return new ctor(hour, minute); 90 | } 91 | 92 | class DigitalClock implements ClockInterface { 93 | constructor(h:number, m:number) { 94 | } 95 | 96 | tick() { 97 | console.log("beep beep"); 98 | } 99 | } 100 | 101 | class AnalogClock implements ClockInterface { 102 | 103 | constructor(h:number, m:number) { 104 | } 105 | 106 | tick() { 107 | console.log("tick tick"); 108 | } 109 | } 110 | 111 | let digital = createClock(DigitalClock, 12, 17); 112 | let analog = createClock(AnalogClock, 7, 32); 113 | 114 | //接口继承类 115 | class Control { 116 | private state:any; 117 | } 118 | 119 | interface SelectableControl extends Control { 120 | select(): void; 121 | } 122 | 123 | class Button extends Control { 124 | select() { 125 | 126 | } 127 | } 128 | 129 | class TextBox extends Control { 130 | select() {} 131 | } 132 | 133 | class Image extends Control { 134 | 135 | } 136 | -------------------------------------------------------------------------------- /typescript-demo/greeter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TypeScript Greeter 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /typescript-demo/greeter.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | } 5 | 6 | class Student { 7 | fullName:string; 8 | 9 | constructor(public firstName, public middleInitial, public lastName) { 10 | this.fullName = firstName + " " + middleInitial + " " + lastName; 11 | } 12 | } 13 | 14 | function greeter(person:Person) { 15 | let name:string = 'bob'; 16 | name = "smith"; 17 | let age: number = 37; 18 | let sentence: string = ` 19 | Hello, my name is ${ name }. 20 | 21 | I'll be ${age + 1} years old next month. 22 | `; 23 | 24 | let list: number[] = [1,2,3]; 25 | let list1: Array = [4,5,6]; 26 | let list2: Array = ["first", "second", "third"]; 27 | 28 | 29 | let x: [string, number]; 30 | x = ['Hello', 10]; 31 | 32 | console.log(x[0].substr(1)); 33 | console.log(x[1]); 34 | 35 | x[3] = 'world'; 36 | console.log(x[3].toString()); 37 | 38 | 39 | enum Color {Red, Green, Blue}; 40 | let c: Color = Color.Green; 41 | console.log(c); 42 | 43 | let colorName: string = Color[2]; 44 | //alert(colorName); 45 | 46 | //Object 47 | let notSure: Object = 4; 48 | notSure = "maybe a string instead"; 49 | console.log(notSure); 50 | notSure = false; 51 | console.log(notSure); 52 | 53 | //any 54 | //let notSure: any = 4; 55 | //notSure = "maybe a string instead"; 56 | //console.log(notSure); 57 | //notSure = false; 58 | 59 | //notSure.ifIExists(); 60 | //notSure.toFixed(); 61 | 62 | let listany: any[] = [1, true, "free"]; 63 | console.log(listany); 64 | 65 | 66 | //null / void 67 | function warnUser(): void { 68 | alert("This is my warning message"); 69 | } 70 | 71 | let unusable: void = undefined; 72 | 73 | //Null / Undefined 74 | let number1: number = null; 75 | //let number1: number = undefined; 76 | console.log(number1); 77 | 78 | //类型断言 79 | let someValue: any = "this is a string"; 80 | //let strLength: number = (someValue).length; 81 | let strLength: number = (someValue as string).length; 82 | 83 | console.log(strLength); 84 | 85 | 86 | 87 | 88 | 89 | return "Hello, " + person.firstName + " " 90 | + person.lastName; 91 | } 92 | 93 | //let const var 94 | //var a = 10; 95 | //function f() { 96 | // var a = 10; 97 | // console.log("aaa = " + a); 98 | // return function g() { 99 | // var b = a + 1; 100 | // console.log("bbb = " + b); 101 | // return b; 102 | // } 103 | //} 104 | 105 | function f() { 106 | var a = 1; 107 | a = 2; 108 | var b = g(); 109 | a = 3; 110 | return b; 111 | 112 | //console.log("aaa = " + a); 113 | function g() { 114 | return a; 115 | } 116 | } 117 | 118 | console.log( f()); 119 | 120 | //for (var i = 0; i < 10; i++) { 121 | // setTimeout(function() { 122 | // console.log(i); 123 | // }, 100 * i); 124 | //} 125 | 126 | //重要打印 i 127 | //for(var i = 0; i < 10; i++) { 128 | // (function(i){ 129 | // setTimeout(function() { 130 | // console.log(i); 131 | // }, 100 * i); 132 | // })(i); 133 | //} 134 | 135 | //let 块作用域 136 | function letf(input: boolean) { 137 | let a = 100; 138 | if(input) { 139 | let b = a + 1; 140 | return b; 141 | } 142 | //return b; 143 | } 144 | 145 | function foo() { 146 | return a; 147 | } 148 | 149 | foo(); 150 | let a; 151 | 152 | 153 | //let 的优势 154 | //for(let i = 0; i< 10; i++) { 155 | // setTimeout(function() { 156 | // console.log(i); 157 | // }, 100 * i); 158 | //} 159 | 160 | //let or const 161 | const con1 = 10; 162 | 163 | const kitty = { 164 | name: "111", 165 | num: 100 166 | }; 167 | console.log(kitty); 168 | 169 | kitty.name = "Rory"; 170 | kitty.num = 200; 171 | console.log(kitty); 172 | 173 | 174 | let input = [1,2]; 175 | //let [first, second] = input; 176 | //console.log(first); 177 | //console.log(second); 178 | 179 | //[first, second] = [second, first]; 180 | // 181 | //console.log(first); 182 | //console.log(second); 183 | 184 | function fjiegou([first, second]: [number, number]) { 185 | console.log(first); 186 | console.log(second); 187 | } 188 | 189 | //fjiegou([1,2]); 190 | 191 | //let [first, ...rest] = [1, 2, 3, 4]; 192 | //console.log(first); 193 | //console.log(rest); 194 | 195 | 196 | var user = new Student("Jane", "M.", "User"); 197 | document.body.innerHTML = greeter(user); -------------------------------------------------------------------------------- /typescript-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-typescript-demo", 3 | "version": "0.0.1", 4 | "license": "ISC", 5 | "dependencies": { 6 | "react": "^15.3.2", 7 | "react-dom": "^15.3.2", 8 | "typescript": "^2.0.6" 9 | }, 10 | "description": "just for test ts and webpack", 11 | "main": "./lib/bundle.js", 12 | "devDependencies": { 13 | "source-map-loader": "^0.1.5", 14 | "ts-loader": "^0.9.5" 15 | }, 16 | "scripts": { 17 | "test": "echo \"Error: no test specified\" && exit 1" 18 | }, 19 | "author": "tancolo" 20 | } 21 | -------------------------------------------------------------------------------- /typescript-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "noImplicitAny": true, 5 | "removeComments": true, 6 | "preserveConstEnums": true, 7 | "outDir": "build", 8 | "sourceMap": false 9 | }, 10 | "files": [ 11 | "greeter.ts", 12 | "TsClass.ts", 13 | "TsInterface.ts" 14 | ] 15 | } --------------------------------------------------------------------------------