45 |
46 |
47 | Getting Started with Angular - The Fundamentals
48 | Core Directives - ngStyle and ngClass
49 |
50 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/core-directives-ngstyle-ngclass/lesson.css:
--------------------------------------------------------------------------------
1 |
2 | .lesson {
3 | text-align: left;
4 | }
5 |
6 | table td, table th {
7 | padding: 5px 8px;
8 | }
9 |
10 | .marvel {
11 | background: #b13138;
12 | border: 1px solid gray;
13 | color: white;
14 | }
15 |
16 | .marvel.hulk {
17 | background: green;
18 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/core-directives-ngstyle-ngclass/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/directives-intro/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component} from "@angular/core";
3 | import {NgModule} from "@angular/core";
4 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
5 | import {BrowserModule} from "@angular/platform-browser";
6 |
7 | import {CollapseOnClick} from "./collapse-on-click.directive";
8 |
9 |
10 |
11 | @Component({
12 | selector:'app',
13 | template: `
14 |
15 |
17 |
18 |
arrow_drop_down
19 |
arrow_drop_up
20 |
21 |
22 | This page section is collapsible, double click it and it will collapse or expand.
23 |
24 |
25 | `
26 | })
27 | export class App {
28 |
29 |
30 | }
31 |
32 | @NgModule({
33 | declarations: [App, CollapseOnClick],
34 | imports: [BrowserModule],
35 | bootstrap: [App]
36 | })
37 | export class AppModule {
38 |
39 | }
40 |
41 | platformBrowserDynamic().bootstrapModule(AppModule);
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/directives-intro/collapse-on-click.directive.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Directive, HostBinding, HostListener, Input, Output, EventEmitter,Optional} from "@angular/core";
3 |
4 | @Directive({
5 | selector: '[collapse-on-click]',
6 | exportAs: "cp"
7 | })
8 | export class CollapseOnClick {
9 |
10 | @Input("collapsed")
11 | isCollapsed = false;
12 |
13 | @Output("collapsed")
14 | collapsedOutput = new EventEmitter();
15 |
16 | get collapsed() {
17 | return this.isCollapsed;
18 | }
19 |
20 | @HostListener('dblclick')
21 | onDblClick() {
22 | this.isCollapsed = !this.isCollapsed;
23 | this.collapsedOutput.emit(this.isCollapsed);
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/directives-intro/directives-intro.css:
--------------------------------------------------------------------------------
1 |
2 | .lesson.lesson-directives-intro {
3 | max-width: 400px;
4 | cursor: pointer;
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/directives-intro/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
46 |
47 |
48 | Getting Started With Angular
49 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/directives-intro/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/directives/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component} from "@angular/core";
3 | import {NgModule} from "@angular/core";
4 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
5 | import {BrowserModule} from "@angular/platform-browser";
6 |
7 | import {ShowOneContainer} from "./show-one-container";
8 | import {ShowOne} from "./show-one";
9 | import {ShowOneTrigger} from "./show-one-trigger";
10 |
11 |
12 | @Component({
13 | selector: 'app',
14 | template: `
15 |
16 |
45 |
46 |
47 | Getting Started with Angular - The Fundamentals
48 | Directives Essentials
49 |
50 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/directives/lesson.css:
--------------------------------------------------------------------------------
1 |
2 | .lesson {
3 | text-align: left;
4 | }
5 |
6 |
7 | .toggle-panel {
8 | background: #d00000;
9 | color: white;
10 | padding: 5px 10px;
11 | border:1px solid gray;
12 | border-radius: 4px;
13 | width: 100px;
14 | height: 50px;
15 | margin-bottom: 20px;
16 | }
17 |
18 | .logo {
19 | background-repeat: no-repeat;
20 | background-size: 80px;
21 | background-position-x: center;
22 | background-position-y: center;
23 | height: 50px;
24 | margin: 0 auto;
25 | padding: 30px 0;
26 | }
27 |
28 | .superman {
29 | background-image: url('/images/superman.png');
30 | }
31 |
32 | .batman {
33 | background-image: url('/images/batman.jpg');
34 | }
35 |
36 | .flash {
37 | background-image: url('/images/flash.svg');
38 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/directives/show-one-container.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {Directive, ContentChildren, QueryList} from "@angular/core";
4 | import {ShowOne} from "./show-one";
5 | import {ShowOneTrigger} from "./show-one-trigger";
6 |
7 |
8 | @Directive({
9 | selector: '[showOneContainer]'
10 | })
11 | export class ShowOneContainer {
12 |
13 | triggers: ShowOneTrigger[] = [];
14 |
15 | @ContentChildren(ShowOne)
16 | items: QueryList;
17 |
18 | add(trigger: ShowOneTrigger) {
19 | this.triggers.push(trigger);
20 | }
21 |
22 | show(id:string) {
23 | this.items.forEach(item => item.active = item.id == id);
24 | this.triggers.forEach(
25 | (trigger:ShowOneTrigger) => trigger.active = trigger.id == id);
26 | }
27 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/directives/show-one-trigger.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {Directive, HostListener, HostBinding, Input} from "@angular/core";
4 | import {ShowOneContainer} from "./show-one-container";
5 |
6 |
7 | @Directive({
8 | selector: '[showOneTrigger]'
9 | })
10 | export class ShowOneTrigger {
11 |
12 | @Input("showOneTrigger")
13 | id: string;
14 |
15 | @Input()
16 | active = false;
17 |
18 | constructor(private showOneContainer: ShowOneContainer) {
19 | showOneContainer.add(this);
20 | }
21 |
22 | @HostListener('click')
23 | click() {
24 | this.showOneContainer.show(this.id);
25 | }
26 |
27 | @HostBinding('class.selected')
28 | get selected() {
29 | return this.active;
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/directives/show-one.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {Directive, HostBinding, Input} from "@angular/core";
4 |
5 |
6 | @Directive({
7 | selector: '[showOne]'
8 | })
9 | export class ShowOne {
10 |
11 | @Input("showOne")
12 | id:string;
13 |
14 | @Input()
15 | active = false;
16 |
17 | @HostBinding('hidden')
18 | get hidden() {
19 | return !this.active;
20 | }
21 |
22 |
23 |
24 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/directives/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/exercise-color-sample/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component} from "@angular/core";
3 | import {NgModule} from "@angular/core";
4 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
5 | import {BrowserModule} from "@angular/platform-browser";
6 |
7 | import {ColorSample} from "./color-sample";
8 |
9 | @Component({
10 | selector:'app',
11 | template: `
12 | `
14 | })
15 | export class App {
16 |
17 | color: string;
18 |
19 | onType(newColor) {
20 | this.color = newColor;
21 | }
22 |
23 | }
24 |
25 | @NgModule({
26 | declarations: [App, ColorSample],
27 | imports: [BrowserModule],
28 | bootstrap: [App]
29 | })
30 | export class AppModule {
31 |
32 | }
33 |
34 | platformBrowserDynamic().bootstrapModule(AppModule);
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/exercise-color-sample/color-sample.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {Component, Input} from "@angular/core";
4 |
5 | @Component({
6 | selector:'color-sample',
7 | template: ``
9 | })
10 | export class ColorSample {
11 |
12 | @Input()
13 | color:string;
14 |
15 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/exercise-color-sample/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Really Understanding Angular - The Fundamentals
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
35 |
36 |
37 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 | Really Understanding Angular - The Fundamentals
48 |
49 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/exercise-color-sample/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-model-driven/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component, NgModule} from "@angular/core";
3 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
4 | import {BrowserModule} from "@angular/platform-browser";
5 | import {FormGroup, FormControl, Validators, FormBuilder, ReactiveFormsModule} from "@angular/forms";
6 | import {Lesson, StudentLevel} from "./lesson";
7 | import "rxjs/Rx";
8 | import {validateDuration} from "./validateDuration";
9 |
10 |
11 | @Component({
12 | selector:'app',
13 | template: `
14 |
15 | Model Driven Forms
16 |
17 |
42 |
43 |
44 |
45 | `
46 | })
47 | export class App {
48 |
49 | myForm: FormGroup;
50 |
51 | duration = new FormControl(10, [validateDuration]);
52 |
53 | lesson = new Lesson(
54 | "Title goes here",
55 | 0,
56 | "Description goes here",
57 | "Transcript goes here",
58 | StudentLevel.BEGINNER
59 | );
60 |
61 | constructor(fb: FormBuilder) {
62 |
63 | this.myForm = fb.group({
64 | title: ['This is the title', [
65 | Validators.minLength(5) ]
66 | ],
67 | duration: this.duration,
68 | description: ['description goes here',[Validators.required]]
69 | });
70 |
71 |
72 |
73 |
74 |
75 |
76 | this.myForm.valueChanges
77 | .filter(() => this.myForm.valid)
78 | .map(value => new Lesson(value.title, value.duration,
79 | value.description,"",StudentLevel.BEGINNER))
80 | .do(formValue => console.log("Valid Form Value:", formValue))
81 | .subscribe(
82 | lesson => this.lesson = lesson
83 | );
84 |
85 | }
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | partialUpdate() {
95 | this.myForm.patchValue({
96 | title: "Set Form Values",
97 | duration: 5
98 | });
99 | }
100 |
101 | fullUpdate() {
102 | this.myForm.setValue({
103 | title: "Set Form Values",
104 | description: "new description"
105 | });
106 | }
107 |
108 | reset() {
109 | this.myForm.reset();
110 | }
111 |
112 |
113 | }
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | @NgModule({
140 | declarations: [App],
141 | imports: [BrowserModule, ReactiveFormsModule],
142 | bootstrap: [App]
143 | })
144 | export class AppModule {
145 |
146 | }
147 |
148 | platformBrowserDynamic().bootstrapModule(AppModule);
149 |
150 |
151 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-model-driven/checkIfTitleExists.ts:
--------------------------------------------------------------------------------
1 |
2 | import {FormControl} from "@angular/forms";
3 | import {HTTP_PROVIDERS, Http, URLSearchParams} from "@angular/http";
4 | import {Observable} from "rxjs/Rx";
5 |
6 |
7 | /*
8 | *
9 | * Asynchronous validators with Observables are still being worked on by the Angular Team.
10 | *
11 | * This will the subject of a future lesson.
12 | *
13 | * */
14 |
15 | export function checkIfTitleExists(http:Http, ctrl: FormControl): Observable {
16 |
17 | const search: URLSearchParams = new URLSearchParams();
18 | search.set('search', ctrl.value);
19 |
20 | return http.get('/lessons', {search:search})
21 | .do(() => console.log('request sent ...'))
22 | .map(res => {
23 |
24 | const lesson = res.json();
25 |
26 | return !lesson ? null : {
27 | titleExists: {
28 | valid:false
29 | }
30 | };
31 | });
32 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-model-driven/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Really Understanding Angular - The Fundamentals
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
35 |
36 |
37 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 |
48 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-model-driven/lesson.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | export enum StudentLevel {
4 | BEGINNER,
5 | ADVANCED
6 | }
7 |
8 |
9 | export class Lesson {
10 |
11 | id:string;
12 |
13 | constructor(public title:string, duration:number, public description:string,
14 | public transcript:string, private _level:StudentLevel) {
15 |
16 | }
17 |
18 | set level(level:string) {
19 | console.log("setting lesson level...");
20 | this._level = StudentLevel[level];
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-model-driven/number-field.component.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {Component} from "@angular/core";
4 | import {Component, Provider, forwardRef} from "@angular/core";
5 | import {ControlValueAccessor, NG_VALUE_ACCESSOR, CORE_DIRECTIVES} from "@angular/common";
6 |
7 |
8 | export const NUMBER_FIELD_CONTROL_VALUE_ACCESSOR: any = {
9 | provide: NG_VALUE_ACCESSOR,
10 | useExisting: forwardRef(() => NumberField),
11 | multi: true
12 | };
13 |
14 |
15 | @Component({
16 | selector: 'number-field',
17 | providers: [NUMBER_FIELD_CONTROL_VALUE_ACCESSOR],
18 | template: ``
19 | })
20 | export class NumberField implements ControlValueAccessor {
21 |
22 | numValue = 0;
23 |
24 | private _onTouchedCallback = (value:number) => {};
25 |
26 | private _onChangeCallback = (value:number) => {};
27 |
28 |
29 | valueAccessor(): any { return this.numValue; };
30 |
31 | set value(v: any) {
32 | if (v !== this.numValue) {
33 | this.numValue = v;
34 | this._onChangeCallback(v);
35 | }
36 | }
37 |
38 | writeValue(value):void {
39 | this.numValue = value;
40 | }
41 |
42 | registerOnChange(callback) {
43 | this._onChangeCallback = callback;
44 | }
45 |
46 | registerOnTouched(callback) {
47 | this._onTouchedCallback = callback;
48 | }
49 |
50 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-model-driven/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-model-driven/validateDuration.ts:
--------------------------------------------------------------------------------
1 |
2 | import {FormControl} from "@angular/forms";
3 |
4 |
5 | export function validateDuration(ctrl: FormControl) {
6 |
7 | const numValue = parseInt(ctrl.value);
8 |
9 | const valid = numValue && numValue < 10;
10 |
11 | return valid ? null : {
12 | validateDuration: {
13 | valid:false
14 | }
15 | };
16 |
17 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-signup-exercise/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component} from "@angular/core";
3 | import {NgModule} from "@angular/core";
4 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
5 | import {BrowserModule} from "@angular/platform-browser";
6 | import {FormsModule, FormControl, ReactiveFormsModule} from "@angular/forms";
7 | import {confirmPassword} from "./confirmPassword";
8 |
9 |
10 | @Component({
11 | selector:'app',
12 | template: `
13 |
14 | Sign Up To Our Website
15 |
16 |
48 |
49 |
50 |
Form Value:
51 | {{ f.value | json }}
52 |
53 |
54 | `
55 | })
56 | export class App {
57 |
58 | signup = {};
59 |
60 | confirm = new FormControl('', [confirmPassword.bind(undefined, this.signup)]);
61 |
62 | signUp() {
63 | console.log("Sign Up Data:" , this.signup);
64 | }
65 |
66 |
67 | }
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | @NgModule({
89 | declarations: [App],
90 | imports: [BrowserModule, FormsModule, ReactiveFormsModule],
91 | bootstrap: [App]
92 | })
93 | export class AppModule {
94 |
95 | }
96 |
97 | platformBrowserDynamic().bootstrapModule(AppModule);
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-signup-exercise/confirmPassword.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | export function confirmPassword(signup, ctrl) {
5 |
6 | const valid = signup.password && signup.password === ctrl.value;
7 |
8 | return valid ? null : {
9 | confirmPassword:false
10 | };
11 |
12 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-signup-exercise/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Really Understanding Angular - The Fundamentals
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
35 |
36 |
37 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 |
48 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-signup-exercise/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-template-driven/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component, NgModule} from "@angular/core";
3 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
4 | import {BrowserModule} from "@angular/platform-browser";
5 | import {Lesson} from "./lesson";
6 | import {FormsModule} from "@angular/forms";
7 | import {DurationValidator} from "./validate-duration.directive";
8 |
9 |
10 | @Component({
11 | selector:'app',
12 | template: `
13 |
14 | Create Lesson Form - Template Driven
15 |
16 |
55 |
56 |
57 |
Form Value:
58 | {{ f.value | json }}
59 |
60 |
61 |
62 | `
63 | })
64 | export class App {
65 |
66 | lesson = new Lesson();
67 |
68 | createLesson(form) {
69 | console.log("Lesson Value:", this.lesson, form);
70 | debugger;
71 | }
72 |
73 |
74 | summaryStatus(summary) {
75 | return {
76 | color: !summary.valid && !summary.pristine ? 'red' : 'black'
77 | }
78 | }
79 |
80 | }
81 |
82 |
83 | @NgModule({
84 | declarations: [App, DurationValidator],
85 | imports: [BrowserModule, FormsModule],
86 | bootstrap: [App]
87 | })
88 | export class AppModule {
89 |
90 | }
91 |
92 | platformBrowserDynamic().bootstrapModule(AppModule);
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-template-driven/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Really Understanding Angular - The Fundamentals
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
35 |
36 |
37 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-template-driven/lesson.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | export enum StudentLevel {
4 | BEGINNER,
5 | ADVANCED
6 | }
7 |
8 |
9 |
10 | export class Lesson {
11 |
12 | public id:string;
13 |
14 | constructor(
15 | public title = "",
16 | public duration = 0,
17 | public description = "",
18 | private _level = StudentLevel.BEGINNER) {
19 |
20 | }
21 |
22 | set level(level:string) {
23 | console.log("setting lesson level...");
24 | this._level = StudentLevel[level];
25 | }
26 |
27 | get level() {
28 | return StudentLevel[this._level];
29 | }
30 |
31 |
32 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-template-driven/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-template-driven/validate-duration.directive.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Directive, forwardRef} from "@angular/core";
3 | import {Validator, FormControl, NG_VALIDATORS} from "@angular/forms";
4 | import {validateDuration} from "./validateDuration";
5 |
6 |
7 | export const MIN_LENGTH_VALIDATOR = {
8 | provide: NG_VALIDATORS,
9 | multi:true,
10 | useExisting: forwardRef(() => DurationValidator)
11 | };
12 |
13 |
14 |
15 | @Directive({
16 | selector: '[duration][ngModel]',
17 | providers: [MIN_LENGTH_VALIDATOR]
18 | })
19 | export class DurationValidator implements Validator {
20 |
21 |
22 | validate(c: FormControl): {[key:string]:any} {
23 | return validateDuration(c);
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/forms-template-driven/validateDuration.ts:
--------------------------------------------------------------------------------
1 |
2 | import {FormControl} from '@angular/forms';
3 |
4 |
5 | export function validateDuration(ctrl: FormControl) {
6 |
7 | const valid = ctrl.value && parseInt(ctrl.value) && parseInt(ctrl.value) < 10;
8 |
9 | return valid ? null : {
10 | validateDuration: {
11 | valid:false
12 | }
13 | };
14 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/introduction-to-pipes/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component, NgModule} from "@angular/core";
3 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
4 | import {BrowserModule} from "@angular/platform-browser";
5 | import {SortPipe} from "./sort.pipe";
6 |
7 |
8 | @Component({
9 | selector: 'app',
10 | template: `
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 | export class App {
47 |
48 |
49 | message = 'Hello World !';
50 |
51 | date = new Date();
52 |
53 | pi = 3.14159265359;
54 |
55 | percentage = 0.0234;
56 |
57 | amount = 12.1234;
58 |
59 | data = ['A', 'B', 'H', 'C'];
60 |
61 | }
62 |
63 | @NgModule({
64 | declarations: [App, SortPipe],
65 | imports: [BrowserModule],
66 | bootstrap: [App]
67 | })
68 | export class AppModule {
69 |
70 | }
71 |
72 | platformBrowserDynamic().bootstrapModule(AppModule);
73 |
74 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/introduction-to-pipes/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Getting Started With Angular - The Fundamentals
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
35 |
36 |
37 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 | Getting Started with Angular - The Fundamentals
48 | Introduction to Pipes
49 |
50 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/introduction-to-pipes/lesson.css:
--------------------------------------------------------------------------------
1 |
2 | .lesson {
3 | text-align: left;
4 | }
5 |
6 | .pipe-example {
7 | margin-bottom: 10px;
8 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/introduction-to-pipes/sort.pipe.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Pipe, PipeTransform} from "@angular/core";
3 |
4 | @Pipe({
5 | name: 'sort'
6 | })
7 | export class SortPipe implements PipeTransform {
8 |
9 | transform(array: any[], args): any[] {
10 |
11 | let sorted = array.sort();
12 |
13 | if (args.length > 0 && args === 'DESC' ) {
14 | sorted = sorted.reverse();
15 | }
16 |
17 | return sorted;
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/introduction-to-pipes/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component, NgModule} from "@angular/core";
3 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
4 | import {BrowserModule} from "@angular/platform-browser";
5 | import {HttpModule} from "@angular/http";
6 | import "rxjs/Rx";
7 | import {LessonsService} from "./lessons.service";
8 | import {LessonsList} from "./lessons-list.component";
9 |
10 |
11 | @Component({
12 | selector:'app',
13 | template: `
14 |
15 |
17 |
18 |
19 |
20 | `
21 | })
22 | export class App {
23 |
24 | constructor(private lessonsService: LessonsService) {
25 |
26 | }
27 |
28 | }
29 |
30 | @NgModule({
31 | declarations: [App, LessonsList],
32 | imports: [BrowserModule, HttpModule],
33 | bootstrap: [App],
34 | providers: [LessonsService]
35 | })
36 | export class AppModule {
37 |
38 | }
39 |
40 |
41 |
42 | platformBrowserDynamic().bootstrapModule(AppModule);
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Really Understanding Angular - The Fundamentals
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
35 |
36 |
37 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 | Introduction To Angular
48 |
49 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/lessons-list.component.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6 | return c > 3 && r && Object.defineProperty(target, key, r), r;
7 | };
8 | var __metadata = (this && this.__metadata) || function (k, v) {
9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10 | };
11 | var core_1 = require("@angular/core");
12 | var lessons_service_1 = require("./lessons.service");
13 | var LessonsList = (function () {
14 | function LessonsList(lessonsService) {
15 | this.lessonsService = lessonsService;
16 | this.lessons = [];
17 | }
18 | __decorate([
19 | core_1.Input(),
20 | __metadata('design:type', Object)
21 | ], LessonsList.prototype, "lessons", void 0);
22 | LessonsList = __decorate([
23 | core_1.Component({
24 | selector: 'lessons-list',
25 | template: "\n \n \n \n \n | \n \n {{lesson.description}} \n | \n \n \n | \n
\n
\n\n "
26 | }),
27 | __metadata('design:paramtypes', [lessons_service_1.LessonsService])
28 | ], LessonsList);
29 | return LessonsList;
30 | }());
31 | exports.LessonsList = LessonsList;
32 | //# sourceMappingURL=lessons-list.component.js.map
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/lessons-list.component.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"lessons-list.component.js","sourceRoot":"","sources":["lessons-list.component.ts"],"names":[],"mappings":";;;;;;;;;;AACA,qBAA+B,eAAe,CAAC,CAAA;AAC/C,gCAA6B,mBAAmB,CAAC,CAAA;AAuBjD;IAOI,qBAAoB,cAA8B;QAA9B,mBAAc,GAAd,cAAc,CAAgB;QAHlD,YAAO,GAAG,EAAE,CAAC;IAKb,CAAC;IAND;QAAC,YAAK,EAAE;;gDAAA;IAvBZ;QAAC,gBAAS,CAAC;YACP,QAAQ,EAAC,cAAc;YACvB,QAAQ,EAAE,ynBAgBL;SACR,CAAC;;mBAAA;IAeF,kBAAC;AAAD,CAAC,AAdD,IAcC;AAdY,mBAAW,cAcvB,CAAA"}
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/lessons-list.component.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component, Input} from "@angular/core";
3 | import {LessonsService} from "./lessons.service";
4 |
5 |
6 | @Component({
7 | selector:'lessons-list',
8 | template: `
9 |
10 |
11 |
12 |
14 | |
15 |
16 | {{lesson.description}}
17 | |
18 |
19 |
20 | |
21 |
22 |
23 |
24 | `
25 | })
26 | export class LessonsList {
27 |
28 |
29 | @Input()
30 | lessons = [];
31 |
32 |
33 | constructor(private lessonsService: LessonsService) {
34 |
35 | }
36 |
37 |
38 |
39 |
40 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/lessons.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.lessonsData = [
3 | {
4 | id: 1,
5 | url: 'angular2-hello-world-write-first-application',
6 | description: 'Build Your First App - Hello World Step By Step',
7 | duration: '2:49',
8 | tags: "BEGINNER"
9 | },
10 | {
11 | id: 2,
12 | url: 'angular2-build-your-first-component',
13 | description: 'Building Your First Component',
14 | duration: '2:07',
15 | tags: "BEGINNER"
16 | },
17 | {
18 | id: 3,
19 | url: 'angular2-passing-data-to-component-using-input',
20 | description: 'Component @Input - How To Pass Input Data To a Component',
21 | duration: '2:33',
22 | tags: "BEGINNER"
23 | },
24 | {
25 | id: 4,
26 | url: 'angular2-component-events',
27 | description: 'Component Events - Using @Output to create custom events',
28 | duration: '4:44',
29 | tags: "BEGINNER"
30 | },
31 | {
32 | id: 5,
33 | url: 'angular2-component-templates-internal-vs-external',
34 | description: 'Component Templates - Inline Vs External',
35 | duration: '2:55',
36 | tags: "BEGINNER"
37 | },
38 | {
39 | id: 6,
40 | url: 'angular2-components-styling-component-isolation',
41 | description: 'Styling Components - Learn About Component Style Isolation',
42 | duration: '3:27',
43 | tags: "BEGINNER"
44 | },
45 | {
46 | id: 7,
47 | url: 'angular2-components-component-interaction',
48 | description: 'Component Interaction - Extended Components Example',
49 | duration: '5:27',
50 | tags: "BEGINNER"
51 | },
52 | {
53 | id: 8,
54 | url: 'angular2-components-exercise',
55 | description: 'Components Exercise !',
56 | duration: '1:26',
57 | tags: "BEGINNER"
58 | },
59 | {
60 | id: 9,
61 | url: 'angular2-components-exercise-solution',
62 | description: 'Components Exercise Solution Inside',
63 | duration: '2:08',
64 | tags: "BEGINNER"
65 | }
66 | ];
67 | //# sourceMappingURL=lessons.js.map
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/lessons.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"lessons.js","sourceRoot":"","sources":["lessons.ts"],"names":[],"mappings":";AAAa,mBAAW,GAAG;IACvB;QACI,EAAE,EAAE,CAAC;QACL,GAAG,EAAE,8CAA8C;QACnD,WAAW,EAAC,iDAAiD;QAC7D,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAC,UAAU;KAClB;IACD;QACI,EAAE,EAAE,CAAC;QACL,GAAG,EAAE,qCAAqC;QAC1C,WAAW,EAAC,+BAA+B;QAC3C,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAC,UAAU;KAClB;IACD;QACI,EAAE,EAAE,CAAC;QACL,GAAG,EAAE,gDAAgD;QACrD,WAAW,EAAC,0DAA0D;QACtE,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAC,UAAU;KAClB;IACD;QACI,EAAE,EAAE,CAAC;QACL,GAAG,EAAE,2BAA2B;QAChC,WAAW,EAAC,0DAA0D;QACtE,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAC,UAAU;KAClB;IACD;QACI,EAAE,EAAE,CAAC;QACL,GAAG,EAAE,mDAAmD;QACxD,WAAW,EAAC,0CAA0C;QACtD,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAC,UAAU;KAClB;IACD;QACI,EAAE,EAAE,CAAC;QACL,GAAG,EAAE,iDAAiD;QACtD,WAAW,EAAC,4DAA4D;QACxE,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAC,UAAU;KAClB;IACD;QACI,EAAE,EAAE,CAAC;QACL,GAAG,EAAE,2CAA2C;QAChD,WAAW,EAAC,qDAAqD;QACjE,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAC,UAAU;KAClB;IACD;QACI,EAAE,EAAE,CAAC;QACL,GAAG,EAAE,8BAA8B;QACnC,WAAW,EAAC,uBAAuB;QACnC,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAC,UAAU;KAClB;IACD;QACI,EAAE,EAAE,CAAC;QACL,GAAG,EAAE,uCAAuC;QAC5C,WAAW,EAAC,qCAAqC;QACjD,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAC,UAAU;KAClB;CACJ,CAAC"}
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/lessons.module.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | import {NgModule} from "@angular/core";
5 | import {LessonsList} from "./lessons-list.component";
6 | import {LessonsService} from "./lessons.service";
7 | import {CommonModule} from "@angular/common";
8 |
9 | @NgModule({
10 | imports: [CommonModule],
11 | declarations: [LessonsList],
12 | exports: [LessonsList],
13 | providers: [LessonsService]
14 | })
15 | export class LessonsModule {
16 |
17 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/lessons.service.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6 | return c > 3 && r && Object.defineProperty(target, key, r), r;
7 | };
8 | var __metadata = (this && this.__metadata) || function (k, v) {
9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10 | };
11 | var core_1 = require("@angular/core");
12 | var http_1 = require("@angular/http");
13 | var xhr_headers_1 = require("./xhr-headers");
14 | var LessonsService = (function () {
15 | function LessonsService(http) {
16 | this.http = http;
17 | this.lessons = [];
18 | this.loadLessons();
19 | }
20 | LessonsService.prototype.loadLessons = function () {
21 | var _this = this;
22 | this.http.get('/lessons')
23 | .map(function (res) { return res.json(); })
24 | .subscribe(function (lessons) { return _this.lessons = lessons; }, function (err) { return console.error(err); });
25 | };
26 | LessonsService.prototype.createLesson = function (description) {
27 | console.log("creating lesson ...");
28 | var lesson = { description: description };
29 | this.lessons.push(lesson);
30 | this.http.post('/lessons', JSON.stringify(lesson), xhr_headers_1.xhrHeaders())
31 | .subscribe(function () { }, function (err) { return console.error(err); });
32 | };
33 | LessonsService.prototype.delete = function (lessonId) {
34 | console.log("deleting lesson ...");
35 | var index = this.lessons.findIndex(function (lesson) { return lesson.id === lessonId; });
36 | this.lessons.splice(index, 1);
37 | this.http.delete("/lessons/" + lessonId, xhr_headers_1.xhrHeaders())
38 | .subscribe(function () { }, function (err) { return console.error(err); });
39 | };
40 | LessonsService = __decorate([
41 | core_1.Injectable(),
42 | __metadata('design:paramtypes', [http_1.Http])
43 | ], LessonsService);
44 | return LessonsService;
45 | }());
46 | exports.LessonsService = LessonsService;
47 | //# sourceMappingURL=lessons.service.js.map
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/lessons.service.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"lessons.service.js","sourceRoot":"","sources":["lessons.service.ts"],"names":[],"mappings":";;;;;;;;;;AACA,qBAAyB,eAAe,CAAC,CAAA;AACzC,qBAAmB,eAAe,CAAC,CAAA;AACnC,4BAAyB,eAAe,CAAC,CAAA;AAIzC;IAII,wBAAoB,IAAU;QAAV,SAAI,GAAJ,IAAI,CAAM;QAF9B,YAAO,GAAG,EAAE,CAAC;QAGT,IAAI,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC;IAED,oCAAW,GAAX;QAAA,iBAOC;QANG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;aACpB,GAAG,CAAC,UAAA,GAAG,IAAI,OAAA,GAAG,CAAC,IAAI,EAAE,EAAV,CAAU,CAAC;aACtB,SAAS,CACN,UAAA,OAAO,IAAI,OAAA,KAAI,CAAC,OAAO,GAAG,OAAO,EAAtB,CAAsB,EACjC,UAAA,GAAG,IAAI,OAAA,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAlB,CAAkB,CAC5B,CAAC;IACV,CAAC;IAED,qCAAY,GAAZ,UAAa,WAAW;QACpB,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,IAAM,MAAM,GAAG,EAAC,aAAA,WAAW,EAAC,CAAC;QAC7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,wBAAU,EAAE,CAAC;aAC3D,SAAS,CACN,cAAO,CAAC,EACR,UAAA,GAAG,IAAI,OAAA,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAlB,CAAkB,CAC5B,CAAC;IACV,CAAC;IAED,+BAAM,GAAN,UAAO,QAAQ;QACX,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,IAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAChC,UAAA,MAAM,IAAI,OAAA,MAAM,CAAC,EAAE,KAAK,QAAQ,EAAtB,CAAsB,CACnC,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,cAAY,QAAU,EAAE,wBAAU,EAAE,CAAC;aACjD,SAAS,CACN,cAAO,CAAC,EACR,UAAA,GAAG,IAAI,OAAA,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAlB,CAAkB,CAC5B,CAAC;IACV,CAAC;IAxCL;QAAC,iBAAU,EAAE;;sBAAA;IA0Cb,qBAAC;AAAD,CAAC,AAzCD,IAyCC;AAzCY,sBAAc,iBAyC1B,CAAA"}
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/lessons.service.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Injectable} from "@angular/core";
3 | import {Http} from "@angular/http";
4 | import {xhrHeaders} from "./xhr-headers";
5 |
6 |
7 | @Injectable()
8 | export class LessonsService {
9 |
10 | lessons = [];
11 |
12 | constructor(private http: Http) {
13 | this.loadLessons();
14 | }
15 |
16 | loadLessons() {
17 | this.http.get('/lessons')
18 | .map(res => res.json())
19 | .subscribe(
20 | lessons => this.lessons = lessons,
21 | err => console.error(err)
22 | );
23 | }
24 |
25 | createLesson(description) {
26 | console.log("creating lesson ...");
27 | const lesson = {description};
28 | this.lessons.push(lesson);
29 | this.http.post('/lessons', JSON.stringify(lesson), xhrHeaders())
30 | .subscribe(
31 | () => {},
32 | err => console.error(err)
33 | );
34 | }
35 |
36 | delete(lessonId) {
37 | console.log("deleting lesson ...");
38 | const index = this.lessons.findIndex(
39 | lesson => lesson.id === lessonId
40 | );
41 | this.lessons.splice(index, 1);
42 | this.http.delete(`/lessons/${lessonId}`, xhrHeaders())
43 | .subscribe(
44 | () => {},
45 | err => console.error(err)
46 | );
47 | }
48 |
49 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/lessons.ts:
--------------------------------------------------------------------------------
1 | export const lessonsData = [
2 | {
3 | id: 1,
4 | url: 'angular2-hello-world-write-first-application',
5 | description:'Build Your First App - Hello World Step By Step',
6 | duration: '2:49',
7 | tags:"BEGINNER"
8 | },
9 | {
10 | id: 2,
11 | url: 'angular2-build-your-first-component',
12 | description:'Building Your First Component',
13 | duration: '2:07',
14 | tags:"BEGINNER"
15 | },
16 | {
17 | id: 3,
18 | url: 'angular2-passing-data-to-component-using-input',
19 | description:'Component @Input - How To Pass Input Data To a Component',
20 | duration: '2:33',
21 | tags:"BEGINNER"
22 | },
23 | {
24 | id: 4,
25 | url: 'angular2-component-events',
26 | description:'Component Events - Using @Output to create custom events',
27 | duration: '4:44',
28 | tags:"BEGINNER"
29 | },
30 | {
31 | id: 5,
32 | url: 'angular2-component-templates-internal-vs-external',
33 | description:'Component Templates - Inline Vs External',
34 | duration: '2:55',
35 | tags:"BEGINNER"
36 | },
37 | {
38 | id: 6,
39 | url: 'angular2-components-styling-component-isolation',
40 | description:'Styling Components - Learn About Component Style Isolation',
41 | duration: '3:27',
42 | tags:"BEGINNER"
43 | },
44 | {
45 | id: 7,
46 | url: 'angular2-components-component-interaction',
47 | description:'Component Interaction - Extended Components Example',
48 | duration: '5:27',
49 | tags:"BEGINNER"
50 | },
51 | {
52 | id: 8,
53 | url: 'angular2-components-exercise',
54 | description:'Components Exercise !',
55 | duration: '1:26',
56 | tags:"BEGINNER"
57 | },
58 | {
59 | id: 9,
60 | url: 'angular2-components-exercise-solution',
61 | description:'Components Exercise Solution Inside',
62 | duration: '2:08',
63 | tags:"BEGINNER"
64 | }
65 | ];
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/xhr-headers.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var http_1 = require("@angular/http");
3 | function xhrHeaders() {
4 | var headers = new http_1.Headers();
5 | headers.append('Content-Type', 'application/json; charset=utf-8');
6 | headers.append('X-Requested-With', 'XMLHttpRequest');
7 | return { headers: headers };
8 | }
9 | exports.xhrHeaders = xhrHeaders;
10 | //# sourceMappingURL=xhr-headers.js.map
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/xhr-headers.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"xhr-headers.js","sourceRoot":"","sources":["xhr-headers.ts"],"names":[],"mappings":";AACA,qBAAsB,eAAe,CAAC,CAAA;AAEtC;IACI,IAAM,OAAO,GAAG,IAAI,cAAO,EAAE,CAAC;IAC9B,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,iCAAiC,CAAC,CAAC;IAClE,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAC,gBAAgB,CAAC,CAAC;IACpD,MAAM,CAAC,EAAC,SAAA,OAAO,EAAC,CAAC;AACrB,CAAC;AALe,kBAAU,aAKzB,CAAA"}
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/modules-intro/xhr-headers.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Headers} from "@angular/http";
3 |
4 | export function xhrHeaders() {
5 | const headers = new Headers();
6 | headers.append('Content-Type', 'application/json; charset=utf-8');
7 | headers.append('X-Requested-With','XMLHttpRequest');
8 | return {headers};
9 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-exercise/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component} from "@angular/core";
3 | import {NgModule} from "@angular/core";
4 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
5 | import {BrowserModule} from "@angular/platform-browser";
6 |
7 | import {RouterModule} from "@angular/router";
8 | import {routeConfig} from "./router-config";
9 | import {DashboardHeader} from "./dashboard-header";
10 | import {PageViewsByBrowserWidget} from "./page-views-by-browser.component";
11 | import {PageViewsPieChartWidget} from "./page-views-pie-chart.component";
12 | import {ImpressionsByCountryWidget} from "./impresssions-by-country.component";
13 |
14 |
15 | @Component({
16 | selector:'app',
17 | template: `
18 |
19 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | `
46 | })
47 | export class App {
48 |
49 |
50 |
51 | }
52 |
53 |
54 | @NgModule({
55 | declarations: [App, DashboardHeader, PageViewsByBrowserWidget, PageViewsPieChartWidget, ImpressionsByCountryWidget],
56 | imports: [BrowserModule, RouterModule.forRoot(routeConfig)],
57 | bootstrap: [App]
58 | })
59 | export class AppModule {
60 |
61 | }
62 |
63 | platformBrowserDynamic().bootstrapModule(AppModule);
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-exercise/dashboard-header.ts:
--------------------------------------------------------------------------------
1 | import {Component} from "@angular/core";
2 | import {Router} from "@angular/router";
3 |
4 | @Component({
5 | selector: 'dashboard',
6 | template: `
7 |
8 | Dashboard
9 | click on a checkbox to include a section
10 |
11 |
12 | Graph 1
14 |
15 | Graph 2
17 |
18 | Graph 3
20 |
21 |
22 | `
23 | })
24 | export class DashboardHeader {
25 |
26 |
27 | constructor(private router: Router) {
28 |
29 | }
30 |
31 | setGraphs(g1, g2, g3) {
32 | console.log(g1, g2, g3);
33 |
34 | let sections = "";
35 |
36 | if (g1) {
37 | sections += "section1:section1";
38 | }
39 |
40 | if (g2) {
41 | if (sections) {
42 | sections += "//";
43 | }
44 | sections += "section2:section2";
45 | }
46 |
47 | if (g3) {
48 | if (sections) {
49 | sections += "//";
50 | }
51 | sections += "section3:section3";
52 | }
53 | let url = '/home';
54 |
55 | if (sections) {
56 | url += `(${sections})`;
57 | }
58 |
59 | console.log(url);
60 | this.router.navigateByUrl(url);
61 |
62 | }
63 |
64 |
65 |
66 |
67 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-exercise/impresssions-by-country.component.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {Component} from "@angular/core";
4 |
5 | @Component({
6 | selector: 'dashboard-section',
7 | template: `
8 |
9 |
10 |
Impressions By Country
11 |

13 |
14 |
15 | `
16 | })
17 | export class ImpressionsByCountryWidget {
18 |
19 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-exercise/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Really Understanding Angular - The Fundamentals
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-exercise/page-views-by-browser.component.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {Component} from "@angular/core";
4 |
5 | @Component({
6 | selector: 'dashboard-section',
7 | template: `
8 |
9 |
10 |
Page Views By Browser
11 |

13 |
14 |
15 | `
16 | })
17 | export class PageViewsByBrowserWidget {
18 |
19 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-exercise/page-views-pie-chart.component.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {Component} from "@angular/core";
4 |
5 | @Component({
6 | selector: 'dashboard-section',
7 | template: `
8 |
9 |
10 |
Pages Views (Pie Chart)
11 |

13 |
14 |
15 | `
16 | })
17 | export class PageViewsPieChartWidget {
18 |
19 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-exercise/router-config.ts:
--------------------------------------------------------------------------------
1 | import {Routes} from "@angular/router";
2 | import {DashboardHeader} from "./dashboard-header";
3 | import {PageViewsByBrowserWidget} from "./page-views-by-browser.component";
4 | import {PageViewsPieChartWidget} from "./page-views-pie-chart.component";
5 | import {ImpressionsByCountryWidget} from "./impresssions-by-country.component";
6 |
7 |
8 | export const routeConfig:Routes = [
9 |
10 | {
11 | path: '',
12 | pathMatch:'full',
13 | redirectTo: '/home'
14 | },
15 | {
16 | path: 'home',
17 | component: DashboardHeader
18 | },
19 | {
20 | path: 'section1',
21 | component: PageViewsByBrowserWidget,
22 | outlet: 'section1'
23 | },
24 | {
25 | path: 'section2',
26 | component: PageViewsPieChartWidget,
27 | outlet: 'section2'
28 | },
29 | {
30 | path: 'section3',
31 | component: ImpressionsByCountryWidget,
32 | outlet: 'section3'
33 | }
34 |
35 |
36 | ];
37 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-exercise/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/all-lessons.component.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component} from "@angular/core";
3 | import {LessonsList} from "./lessons-list.component";
4 | import {lessonsData} from "./lessonsData";
5 |
6 |
7 | @Component({
8 | selector: 'all-lessons',
9 | template: `
10 |
11 | All Lessons
12 |
13 |
14 |
15 | `
16 | })
17 | export class AllLessons {
18 |
19 | lessons = lessonsData.lessons;
20 |
21 |
22 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component, NgModule} from "@angular/core";
3 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
4 | import {BrowserModule} from "@angular/platform-browser";
5 | import {RouterModule} from "@angular/router";
6 | import {routeConfig} from "./router-config";
7 | import {SharedModule} from "./shared.module";
8 | import {Home} from "./home.component";
9 | import {Playlist} from "./playlist.component";
10 | import {AllLessons} from "./all-lessons.component";
11 |
12 |
13 | @Component({
14 | selector:'app',
15 | template: `
16 |
17 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | `
58 | })
59 | export class App {
60 |
61 |
62 |
63 | }
64 |
65 |
66 |
67 | @NgModule({
68 | declarations: [App, Home, Playlist, AllLessons],
69 | imports: [
70 | BrowserModule,
71 | RouterModule.forRoot(routeConfig),
72 | SharedModule
73 | ],
74 | bootstrap: [App]
75 |
76 | })
77 | export class AppModule {
78 |
79 | }
80 |
81 | platformBrowserDynamic().bootstrapModule(AppModule);
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/chat.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {Component} from "@angular/core";
4 |
5 | @Component({
6 | selector:'chat',
7 | template: `
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | `
16 | })
17 | export class Chat {
18 |
19 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/course-detail-activate.guard.ts:
--------------------------------------------------------------------------------
1 | import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot} from "@angular/router";
2 | import {Observable, Subject} from "rxjs/Rx";
3 | import {coursesData} from "./coursesData";
4 |
5 |
6 | export class CanCourseDetailActivate implements CanActivate {
7 |
8 |
9 | canActivate(route:ActivatedRouteSnapshot,
10 | state:RouterStateSnapshot):Observable|boolean {
11 |
12 |
13 | const subject = new Subject();
14 |
15 | setTimeout(() => {
16 |
17 | const index = route.params['id'] - 1;
18 |
19 | const course = coursesData.courses[index];
20 |
21 | subject.next(course ? !course.pro : true);
22 | subject.complete();
23 |
24 | });
25 |
26 | return subject;
27 |
28 | }
29 |
30 |
31 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/course-detail-deactivate.guard.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | import {CanDeactivate, RouterStateSnapshot, ActivatedRouteSnapshot} from "@angular/router";
5 | import {CourseDetail} from "./course-detail.component";
6 | import {Observable} from "rxjs/Rx";
7 |
8 | export class CanCourseDetailDeactivate
9 | implements CanDeactivate {
10 |
11 |
12 | canDeactivate(component:CourseDetail,
13 | route:ActivatedRouteSnapshot,
14 | state:RouterStateSnapshot):Observable|boolean {
15 |
16 |
17 | if (!component.dirty) {
18 | return true;
19 | }
20 |
21 | return confirm("Unsaved changes exist, do you want to exit ?");
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/course-detail.component.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {Component, OnDestroy} from "@angular/core";
4 | import {lessonsData} from "./lessonsData";
5 | import {LessonsList} from "./lessons-list.component";
6 | import {Router, ActivatedRoute} from "@angular/router";
7 | import {Subscription} from "rxjs/Rx";
8 |
9 |
10 | @Component({
11 | selector:'course-detail',
12 | template: `
13 |
14 |
15 |
{{description}} Course id = {{courseId}}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | `
26 | })
27 | export class CourseDetail implements OnDestroy {
28 |
29 |
30 | courseId: number;
31 |
32 | lessons = lessonsData.lessons;
33 | description:string;
34 |
35 | paramsSub: Subscription;
36 | queryParamsSub: Subscription;
37 |
38 | dirty = false;
39 |
40 |
41 |
42 | constructor(route:ActivatedRoute) {
43 |
44 | this.paramsSub = route.params.subscribe(
45 | params =>{
46 | this.courseId = parseInt(params['id']);
47 | this.dirty = false;
48 | }
49 | );
50 |
51 | this.queryParamsSub = route.queryParams.subscribe(
52 | params => {
53 | this.description = params['description'];
54 | }
55 | );
56 |
57 | console.log('observers count',
58 | route.queryParams['observers'].length);
59 |
60 | }
61 |
62 | previous() {
63 | return this.courseId - 1;
64 | }
65 |
66 | next() {
67 | return this.courseId + 1;
68 | }
69 |
70 |
71 | ngOnDestroy() {
72 | this.paramsSub.unsubscribe();
73 | this.queryParamsSub.unsubscribe();
74 | }
75 | }
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/courses-list.component.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component, Input} from "@angular/core";
3 | import {Router, ActivatedRoute} from "@angular/router";
4 |
5 |
6 | @Component({
7 | selector:'courses-list',
8 | template: `
9 |
10 |
12 |
13 |
15 | |
16 |
17 | {{course.description}}
18 | |
19 |
20 |
21 | |
22 |
23 |
24 |
25 |
26 |
27 | `
28 | })
29 | export class CoursesList {
30 |
31 |
32 | @Input()
33 | courses = [];
34 |
35 |
36 | constructor(private router:Router, private route: ActivatedRoute) {
37 |
38 | }
39 |
40 |
41 | openCourse(course, $event) {
42 |
43 | this.router.navigateByUrl(`/courses/${course.id}`);
44 | $event.stopPropagation();
45 |
46 | }
47 |
48 | showCoursePlayList(course) {
49 |
50 | this.router.navigateByUrl(
51 | `/courses(playlist:playlist;description=${course.description})`
52 | );
53 |
54 | }
55 |
56 |
57 |
58 | }
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/courses-router-config.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | import {Playlist} from "./playlist.component";
5 |
6 |
7 | export const coursesRouterConfig = [
8 | {
9 | path: 'courses',
10 | loadChildren: '/src/router-introduction/courses.module'
11 | },
12 | {
13 | path: 'playlist',
14 | component: Playlist,
15 | outlet: 'playlist'
16 | }
17 | ];
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/courses.component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from "@angular/core";
2 | import {coursesData} from "./coursesData";
3 | import {CoursesList} from "./courses-list.component";
4 |
5 |
6 |
7 | @Component({
8 | selector: 'courses',
9 | template: `
10 |
11 | Courses
12 |
13 |
14 |
15 | `
16 | })
17 | export class Courses {
18 |
19 | courses = coursesData.courses;
20 |
21 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/courses.module.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {NgModule} from "@angular/core";
4 | import {CoursesList} from "./courses-list.component";
5 | import {CommonModule} from "@angular/common";
6 | import {Courses} from "./courses.component";
7 | import {CourseDetail} from "./course-detail.component";
8 | import {CanCourseDetailDeactivate} from "./course-detail-deactivate.guard";
9 | import {CanCourseDetailActivate} from "./course-detail-activate.guard";
10 | import {RouterModule} from "@angular/router";
11 | import {SharedModule} from "./shared.module";
12 |
13 |
14 | const routerConfig = [
15 | {
16 | path: '',
17 | component: Courses
18 | },
19 | {
20 | path: 'legacy-list',
21 | redirectTo: '/lessons',
22 | pathMatch: 'full'
23 | },
24 | {
25 | path: ':id',
26 | canActivate: [CanCourseDetailActivate],
27 | canDeactivate: [CanCourseDetailDeactivate],
28 | component: CourseDetail
29 | }
30 | ];
31 |
32 |
33 | @NgModule({
34 | imports: [CommonModule,
35 | RouterModule.forChild(routerConfig), SharedModule],
36 | declarations: [Courses, CoursesList, CourseDetail],
37 | exports: [CoursesList],
38 | providers: [CanCourseDetailDeactivate, CanCourseDetailActivate]
39 | })
40 | export default class CoursesModule {
41 |
42 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/coursesData.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const coursesData = {
4 |
5 | courses: [
6 | {
7 | id:1,
8 | description: "Angular For Beginners",
9 | pro:false
10 | },
11 | {
12 | id:2,
13 | description: "Angular HTTP",
14 | pro:false
15 | },
16 | {
17 | id:3,
18 | description: "Angular Forms",
19 | pro:false
20 | },
21 | {
22 | id:4,
23 | description: "Angular Router",
24 | pro:true
25 | },
26 | {
27 | id:5,
28 | description: "Angular Universal",
29 | pro:false
30 | },
31 | {
32 | id:6,
33 | description: "Progressive Web Apps",
34 | pro:false
35 | }
36 | ]
37 |
38 | };
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/home.component.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component} from "@angular/core";
3 | import {LessonsList} from "./lessons-list.component";
4 | import {lessonsData} from "./lessonsData";
5 |
6 |
7 | @Component({
8 | selector: 'home',
9 | template: `
10 |
11 |
13 |
14 |
15 |
Latest Lessons
16 |
17 |
18 |
19 |
20 | `
21 | })
22 | export class Home {
23 |
24 | lessons = lessonsData.lessons;
25 |
26 |
27 |
28 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Really Understanding Angular - The Fundamentals
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/lesson.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | export class Lesson {
4 |
5 | id:string;
6 | url: string;
7 | description:string;
8 | duration: string;
9 | tags:string;
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/lessons-list.component.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component, Input} from "@angular/core";
3 |
4 |
5 | @Component({
6 | selector:'lessons-list',
7 | template: `
8 |
9 |
10 |
11 |
13 | |
14 |
15 | {{lesson.description}}
16 | |
17 |
18 |
19 | |
20 |
21 |
22 |
23 | `
24 | })
25 | export class LessonsList {
26 |
27 |
28 | @Input()
29 | lessons = [];
30 |
31 |
32 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/lessonsData.ts:
--------------------------------------------------------------------------------
1 | export const lessonsData = {
2 | lessons: [
3 | {
4 | id: 1,
5 | url: 'angular2-hello-world-write-first-application',
6 | description:'Build Your First App - Hello World Step By Step',
7 | duration: '2:49',
8 | tags:"BEGINNER"
9 | },
10 | {
11 | id: 2,
12 | url: 'angular2-build-your-first-component',
13 | description:'Building Your First Component',
14 | duration: '2:07',
15 | tags:"BEGINNER"
16 | },
17 | {
18 | id: 3,
19 | url: 'angular2-passing-data-to-component-using-input',
20 | description:'Component @Input - How To Pass Input Data To a Component',
21 | duration: '2:33',
22 | tags:"BEGINNER"
23 | },
24 | {
25 | id: 4,
26 | url: 'angular2-component-events',
27 | description:'Component Events - Using @Output to create custom events',
28 | duration: '4:44',
29 | tags:"BEGINNER"
30 | },
31 | {
32 | id: 5,
33 | url: 'angular2-component-templates-internal-vs-external',
34 | description:'Component Templates - Inline Vs External',
35 | duration: '2:55',
36 | tags:"BEGINNER"
37 | },
38 | {
39 | id: 6,
40 | url: 'angular2-components-styling-component-isolation',
41 | description:'Styling Components - Learn About Component Style Isolation',
42 | duration: '3:27',
43 | tags:"BEGINNER"
44 | },
45 | {
46 | id: 7,
47 | url: 'angular2-components-component-interaction',
48 | description:'Component Interaction - Extended Components Example',
49 | duration: '5:27',
50 | tags:"BEGINNER"
51 | },
52 | {
53 | id: 8,
54 | url: 'angular2-components-exercise',
55 | description:'Components Exercise !',
56 | duration: '1:26',
57 | tags:"BEGINNER"
58 | },
59 | {
60 | id: 9,
61 | url: 'angular2-components-exercise-solution',
62 | description:'Components Exercise Solution Inside',
63 | duration: '2:08',
64 | tags:"BEGINNER"
65 | }
66 | ]};
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/playlist.component.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {Component} from "@angular/core";
4 | import {lessonsData} from "./lessonsData";
5 | import {LessonsList} from "./lessons-list.component";
6 | import {ActivatedRoute} from "@angular/router";
7 |
8 |
9 | @Component({
10 | selector: 'playlist',
11 | template: `
12 |
13 |
14 |
{{description}}
15 |
16 |
17 |
18 | `
19 | })
20 | export class Playlist {
21 |
22 | description:string;
23 |
24 | lessons = lessonsData.lessons;
25 |
26 |
27 | constructor(route: ActivatedRoute) {
28 |
29 | route.params.subscribe(
30 | params => this.description = params['description']
31 | );
32 |
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/router-config.ts:
--------------------------------------------------------------------------------
1 | import {AllLessons} from "./all-lessons.component";
2 | import {Home} from "./home.component";
3 | import {Route} from "@angular/router";
4 | import {coursesRouterConfig} from "./courses-router-config";
5 |
6 |
7 | const indexRoute:Route = {
8 | path: "",
9 | component: Home
10 | };
11 |
12 | const fallbackRoute:Route = {
13 | path: '**',
14 | component: Home
15 | };
16 |
17 | export const routeConfig = [
18 | {
19 | path: 'home',
20 | component: Home
21 | },
22 | ...coursesRouterConfig,
23 | {
24 | path: 'lessons',
25 | component: AllLessons
26 | },
27 | fallbackRoute,
28 | indexRoute
29 | ];
30 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/router.css:
--------------------------------------------------------------------------------
1 |
2 | .l-header {
3 | height: 58px;
4 | }
5 |
6 | .top-menu {
7 | margin-left: 50px;
8 | }
9 |
10 | .top-menu li {
11 | box-shadow: none !important;
12 | }
13 |
14 | .l-sample-app {
15 | text-align: center;
16 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/shared.module.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import {NgModule} from "@angular/core";
4 | import {LessonsList} from "./lessons-list.component";
5 | import {CommonModule} from "@angular/common";
6 |
7 |
8 | @NgModule({
9 | declarations: [LessonsList],
10 | exports: [LessonsList],
11 | imports: [CommonModule]
12 |
13 | })
14 | export class SharedModule {
15 |
16 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/router-introduction/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-http/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component} from "@angular/core";
3 | import {NgModule} from "@angular/core";
4 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
5 | import {BrowserModule} from "@angular/platform-browser";
6 |
7 | import {LessonsList} from "./lessons-list.component";
8 | import {HttpModule} from "@angular/http";
9 | import "rxjs/Rx";
10 | import {LessonsService} from "./lessons.service";
11 | import {initObservable} from "./init-observable";
12 | import {Observable} from "rxjs/Observable";
13 | import {Lesson} from "./lesson";
14 |
15 | @Component({
16 | selector:'app',
17 | template: `
18 |
19 |
20 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | `
30 | })
31 | export class App {
32 |
33 | lessons$: Observable;
34 |
35 | constructor(private lessonsService: LessonsService) {
36 |
37 | initObservable();
38 |
39 | this.lessons$ = lessonsService.loadLessons();
40 | }
41 |
42 | createLesson(description) {
43 | this.lessonsService.createLesson(description);
44 | }
45 |
46 | chain() {
47 |
48 | const lesson = "Lesson 1";
49 |
50 | const lesson2 = "Lesson2";
51 |
52 | const chain$ = this.lessonsService.createLesson(lesson)
53 | .switchMap(results => {
54 | console.log('result', results);
55 | return this.lessonsService.createLesson(lesson2)
56 | })
57 | .switchMap((results2) => {
58 | console.log(results2);
59 | return this.lessonsService.loadLessons();
60 | })
61 | .cache();
62 |
63 |
64 | this.lessons$ = chain$;
65 |
66 | chain$.subscribe();
67 |
68 |
69 | }
70 |
71 | }
72 |
73 |
74 |
75 | @NgModule({
76 | declarations: [App, LessonsList],
77 | imports: [BrowserModule, HttpModule],
78 | bootstrap: [App],
79 | providers: [LessonsService]
80 | })
81 | export class AppModule {
82 |
83 | }
84 |
85 | platformBrowserDynamic().bootstrapModule(AppModule);
86 |
87 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-http/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Really Understanding Angular - The Fundamentals
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
35 |
36 |
37 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 | Really Understanding Angular - The Fundamentals
48 |
49 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-http/init-observable.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Observable} from "rxjs/Observable";
3 | declare function fetch(url:string);
4 |
5 |
6 |
7 |
8 | export function initObservable() {
9 |
10 | const click$ = Observable.fromEvent(document,'click');
11 |
12 | const mouse$ = Observable.fromEvent(document,'mousemove')
13 | .filter((move:MouseEvent) => move.clientY >=200);
14 |
15 |
16 | const combined$ = Observable.combineLatest(mouse$, click$);
17 | /*
18 | combined$.subscribe(
19 | combined => console.log(combined[0])
20 | );
21 |
22 | */
23 | }
24 |
25 | /*
26 | * // mouse clicks
27 | *
28 | * |------------------------x---------------------x-------....
29 | *
30 | *
31 | * // mouse move
32 | *
33 | * |--(x,y)--(x,y)--(x,y)--(x,y)--(x,y)-(x,y)-(x,y)-(x,y)-(x,y)....
34 | *
35 | *
36 | * // mouse move bellow 200
37 | *
38 | * |----------------(x,y)---------(x,y)----...
39 | *
40 | *
41 | * // combined
42 | *
43 | * |-------------------------(x,y)---.....
44 | *
45 | *
46 | * */
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-http/lesson.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | export class Lesson {
4 |
5 | id:string;
6 | url: string;
7 | description:string;
8 | duration: string;
9 | tags:string;
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-http/lessons-list.component.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component, Input} from "@angular/core";
3 | import {LessonsService} from "./lessons.service";
4 |
5 |
6 | @Component({
7 | selector:'lessons-list',
8 | template: `
9 |
10 |
11 |
12 |
14 | |
15 |
16 | {{lesson.description}}
17 | |
18 |
19 |
20 | |
21 |
22 |
23 |
24 | `
25 | })
26 | export class LessonsList {
27 |
28 |
29 | @Input()
30 | lessons = [];
31 |
32 |
33 | constructor(private lessonsService: LessonsService) {
34 |
35 | }
36 |
37 |
38 |
39 |
40 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-http/lessons.service.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Injectable} from "@angular/core";
3 | import {Http, URLSearchParams} from "@angular/http";
4 | import {xhrHeaders} from "./xhr-headers";
5 | import {Lesson} from "./lesson";
6 | import {Observable} from "rxjs/Observable";
7 |
8 |
9 | @Injectable()
10 | export class LessonsService {
11 |
12 |
13 | constructor(private http: Http) {
14 |
15 | }
16 |
17 | loadLessons(search = ""): Observable {
18 |
19 | console.log(`searching for ${search}`);
20 |
21 | let params: URLSearchParams = new URLSearchParams();
22 | params.set('search', search);
23 |
24 | return this.http.get('/lessons', {search:params}).map(res => res.json());
25 | }
26 |
27 |
28 | loadFlakyLessons() {
29 | return this.http.get('/flakylessons').map(res => res.json());
30 | }
31 |
32 | loadDelayedLessons(search = "") {
33 |
34 | console.log(`searching for ${search}`);
35 |
36 | let params: URLSearchParams = new URLSearchParams();
37 | params.set('search', search);
38 |
39 | return this.http.get('/delayedlessons', {search:params}).map(res => res.json());
40 | }
41 |
42 | createLesson(description) {
43 |
44 | const network$ = this.http.post('/lessons',
45 | JSON.stringify({description}),
46 | xhrHeaders())
47 | .cache();
48 |
49 | network$.subscribe(
50 | () => console.log('HTTP post successful !'),
51 | err => console.error(err),
52 | () => console.log('monitoring completed ...')
53 |
54 | );
55 |
56 | return network$;
57 |
58 | }
59 |
60 | delete(lessonId) {
61 | return this.http.delete(`/lessons/${lessonId}`, xhrHeaders());
62 | }
63 |
64 |
65 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-http/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-http/xhr-headers.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Headers} from "@angular/http";
3 |
4 | export function xhrHeaders() {
5 | const headers = new Headers();
6 | headers.append('Content-Type', 'application/json; charset=utf-8');
7 | headers.append('X-Requested-With','XMLHttpRequest');
8 | return {headers};
9 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-intro/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component} from "@angular/core";
3 | import {NgModule} from "@angular/core";
4 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
5 | import {BrowserModule} from "@angular/platform-browser";
6 |
7 | import {LessonsList} from "./lessons-list.component";
8 | import {HttpModule} from "@angular/http";
9 | import "rxjs/Rx";
10 | import {LessonsService} from "./lessons.service";
11 |
12 |
13 | @Component({
14 | selector:'app',
15 | template: `
16 |
17 |
19 |
20 |
21 |
22 | `
23 | })
24 | export class App {
25 |
26 | constructor(private lessonsService: LessonsService) {
27 |
28 | }
29 |
30 | }
31 |
32 | @NgModule({
33 | declarations: [App, LessonsList],
34 | imports: [BrowserModule, HttpModule],
35 | bootstrap: [App],
36 | providers: [LessonsService]
37 | })
38 | export class AppModule {
39 |
40 | }
41 |
42 |
43 | platformBrowserDynamic().bootstrapModule(AppModule);
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-intro/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Really Understanding Angular - The Fundamentals
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
35 |
36 |
37 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 | Really Understanding Angular - The Fundamentals
48 |
49 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-intro/lessons-list.component.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Component, Input} from "@angular/core";
3 | import {LessonsService} from "./lessons.service";
4 |
5 |
6 | @Component({
7 | selector:'lessons-list',
8 | template: `
9 |
10 |
11 |
12 |
14 | |
15 |
16 | {{lesson.description}}
17 | |
18 |
19 |
20 | |
21 |
22 |
23 |
24 | `
25 | })
26 | export class LessonsList {
27 |
28 |
29 | @Input()
30 | lessons = [];
31 |
32 |
33 | constructor(private lessonsService: LessonsService) {
34 |
35 | }
36 |
37 |
38 |
39 |
40 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-intro/lessons.service.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Injectable} from "@angular/core";
3 | import {Http} from "@angular/http";
4 | import {xhrHeaders} from "./xhr-headers";
5 |
6 |
7 | @Injectable()
8 | export class LessonsService {
9 |
10 | lessons = [];
11 |
12 | constructor(private http: Http) {
13 | this.loadLessons();
14 | }
15 |
16 | loadLessons() {
17 | this.http.get('/lessons')
18 | .map(res => res.json())
19 | .subscribe(
20 | lessons => this.lessons = lessons,
21 | err => console.error(err)
22 | );
23 | }
24 |
25 | createLesson(description) {
26 | console.log("creating lesson ...");
27 | const lesson = {description};
28 | this.lessons.push(lesson);
29 | this.http.post('/lessons', JSON.stringify(lesson), xhrHeaders())
30 | .subscribe(
31 | () => {},
32 | err => console.error(err)
33 | );
34 | }
35 |
36 | delete(lessonId) {
37 | console.log("deleting lesson ...");
38 | const index = this.lessons.findIndex(
39 | lesson => lesson.id === lessonId
40 | );
41 | this.lessons.splice(index, 1);
42 | this.http.delete(`/lessons/${lessonId}`, xhrHeaders())
43 | .subscribe(
44 | () => {},
45 | err => console.error(err)
46 | );
47 | }
48 |
49 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-intro/lessons.ts:
--------------------------------------------------------------------------------
1 | export const lessonsData = [
2 | {
3 | id: 1,
4 | url: 'angular2-hello-world-write-first-application',
5 | description:'Build Your First App - Hello World Step By Step',
6 | duration: '2:49',
7 | tags:"BEGINNER"
8 | },
9 | {
10 | id: 2,
11 | url: 'angular2-build-your-first-component',
12 | description:'Building Your First Component',
13 | duration: '2:07',
14 | tags:"BEGINNER"
15 | },
16 | {
17 | id: 3,
18 | url: 'angular2-passing-data-to-component-using-input',
19 | description:'Component @Input - How To Pass Input Data To a Component',
20 | duration: '2:33',
21 | tags:"BEGINNER"
22 | },
23 | {
24 | id: 4,
25 | url: 'angular2-component-events',
26 | description:'Component Events - Using @Output to create custom events',
27 | duration: '4:44',
28 | tags:"BEGINNER"
29 | },
30 | {
31 | id: 5,
32 | url: 'angular2-component-templates-internal-vs-external',
33 | description:'Component Templates - Inline Vs External',
34 | duration: '2:55',
35 | tags:"BEGINNER"
36 | },
37 | {
38 | id: 6,
39 | url: 'angular2-components-styling-component-isolation',
40 | description:'Styling Components - Learn About Component Style Isolation',
41 | duration: '3:27',
42 | tags:"BEGINNER"
43 | },
44 | {
45 | id: 7,
46 | url: 'angular2-components-component-interaction',
47 | description:'Component Interaction - Extended Components Example',
48 | duration: '5:27',
49 | tags:"BEGINNER"
50 | },
51 | {
52 | id: 8,
53 | url: 'angular2-components-exercise',
54 | description:'Components Exercise !',
55 | duration: '1:26',
56 | tags:"BEGINNER"
57 | },
58 | {
59 | id: 9,
60 | url: 'angular2-components-exercise-solution',
61 | description:'Components Exercise Solution Inside',
62 | duration: '2:08',
63 | tags:"BEGINNER"
64 | }
65 | ];
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-intro/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/services-intro/xhr-headers.ts:
--------------------------------------------------------------------------------
1 |
2 | import {Headers} from "@angular/http";
3 |
4 | export function xhrHeaders() {
5 | const headers = new Headers();
6 | headers.append('Content-Type', 'application/json; charset=utf-8');
7 | headers.append('X-Requested-With','XMLHttpRequest');
8 | return {headers};
9 | }
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/typescript-introduction/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 | "suppressImplicitAnyIndexErrors": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/src/typescript-introduction/typescript-introduction.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | var hello = "Hello World !";
4 |
5 | if (hello) {
6 | console.log(hello);
7 | }
8 |
9 |
10 | const message = `message: ${hello}`;
11 |
12 | console.log(message);
13 |
14 |
15 |
16 | function printMessage(message:string,
17 | callback: Function) {
18 | console.log(message);
19 | callback();
20 | }
21 |
22 |
23 | printMessage(message, () => {
24 | console.log('callback was called ...');
25 | });
26 |
27 |
28 |
--------------------------------------------------------------------------------
/01-getting-started-with-angular2/system.config.js:
--------------------------------------------------------------------------------
1 | (function (global) {
2 |
3 | //map tells the System loader where to look for things
4 | var map = {
5 |
6 | '@angular': '/node_modules/@angular', // sufficient if we didn't pin the version
7 | '@angular/router': '/node_modules/@angular/router' ,
8 | '@angular/forms': '/node_modules/@angular/forms',
9 | 'angular2-in-memory-web-api': 'https://npmcdn.com/angular2-in-memory-web-api', // get latest
10 | 'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.6',
11 | 'ts': 'https://npmcdn.com/plugin-typescript@4.0.10/lib/plugin.js',
12 | 'typescript': 'https://npmcdn.com/typescript@1.9.0-dev.20160409/lib/typescript.js',
13 | };
14 |
15 | //packages tells the System loader how to load when no filename and/or no extension
16 | var packages = {
17 | 'rxjs': {defaultExtension: 'js'},
18 | 'angular2-in-memory-web-api': {main: 'index.js', defaultExtension: 'js'},
19 | };
20 |
21 | var ngPackageNames = [
22 | 'common',
23 | 'compiler',
24 | 'core',
25 | 'http',
26 | 'platform-browser',
27 | 'platform-browser-dynamic',
28 | 'router-deprecated',
29 | 'upgrade',
30 | 'forms',
31 | 'router'
32 | ];
33 |
34 | // Add map entries for each angular package
35 | ngPackageNames.forEach(function (pkgName) {
36 | map['@angular/' + pkgName] = '/node_modules/@angular/' + pkgName;
37 | });
38 |
39 | // Add package entries for angular packages
40 | ngPackageNames.forEach(function (pkgName) {
41 |
42 | // Bundled (~40 requests):
43 | packages['@angular/' + pkgName] = {main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js'};
44 |
45 | // Individual files (~300 requests):
46 | //packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
47 | });
48 |
49 | var config = {
50 | // DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
51 | transpiler: 'ts',
52 | typescriptOptions: {
53 | tsconfig: true
54 | },
55 | meta: {
56 | 'typescript': {
57 | "exports": "ts"
58 | }
59 | },
60 | map: map,
61 | packages: packages
62 | };
63 |
64 | document.SYSTEMJS_CONFIG = config;
65 |
66 | })(this);
67 |
68 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Angular University Lessons Code
2 | Contains the code for several of the [Angular University](https://angular-university.io) courses.
3 |
4 | This course repository is updated to Angular 5, there is a Yarn lock file available.
5 |
6 |
7 | [Angular for Beginners Course](https://angular-university.io/course/getting-started-with-angular2)
8 |
9 | 
10 |
11 |
12 | # Which Course are You Looking For ?
13 |
14 | If you are looking for the code of the following courses, see further the installation instructions on this page:
15 |
16 | - [Angular For Beginners](https://angular-university.io/course/getting-started-with-angular2)
17 | - [Angular Services and HTTP](https://angular-university.io/course/angular2-http)
18 | - [Angular Router](https://angular-university.io/course/angular2-routing)
19 | - [Angular Forms](https://angular-university.io/course/angular2-forms)
20 |
21 | # Angular and Firebase - Build a Web Application Course
22 |
23 | If you are looking for the Angular and Firebase - Build a Web Application Course code, the repo with the full code can be found here:
24 |
25 | [Angular and Firebase - Build a Web Application](https://angular-university.io/course/build-an-application-with-angular2)
26 |
27 | [Github Repo For this course](https://github.com/angular-university/angular-firebase-app)
28 |
29 | 
30 |
31 |
32 | # Complete Typescript 2 Course - Build A REST API
33 |
34 | If you are looking for the Complete Typescript 2 Course - Build a REST API, the repo with the full code can be found here:
35 |
36 | [Complete Typescript 2 Course - Build A REST API](https://angular-university.io/course/typescript-2-tutorial)
37 |
38 | [Github Repo for this course](https://github.com/angular-university/complete-typescript-course)
39 |
40 | 
41 |
42 |
43 | # Angular Ngrx Reactive Extensions Architecture Course
44 |
45 | If you are looking for the Angular Ngrx Reactive Extensions Architecture Course code, the repo with the full code can be found here:
46 |
47 | [Angular Ngrx Reactive Extensions Architecture Course](https://angular-university.io/course/angular2-ngrx)
48 |
49 | [Github repo for this course](https://github.com/angular-university/ngrx-course)
50 |
51 | 
52 |
53 |
54 | # RxJs And Reactive Patterns Angular Architecture Course
55 |
56 | If you are looking for the RxJs And Reactive Patterns Angular Architecture Course code, the repo with the full code can be found here:
57 |
58 | [RxJs and Reactive Patterns Angular Architecture Course](https://angular-university.io/course/reactive-angular-architecture-course)
59 |
60 | [Github repo for this course](https://github.com/angular-university/reactive-patterns-course)
61 |
62 | 
63 |
64 |
65 |
66 | # Installation pre-requisites
67 |
68 | This project has minimal dependencies, you only need node and npm installed on your machine. These are some tutorials to install node in different operating systems.
69 |
70 | *Make sure to install the latest version of Node 6*
71 |
72 | - [Install Node and NPM on Windows](https://www.youtube.com/watch?v=8ODS6RM6x7g)
73 | - [Install Node and NPM on Linux](https://www.youtube.com/watch?v=yUdHk-Dk_BY)
74 | - [Install Node and NPM on Mac](https://www.youtube.com/watch?v=Imj8PgG3bZU)
75 |
76 |
77 | # Installation Instructions
78 |
79 | First clone or download as a Zip file using the green "Clone Or Download" button on the top right of the document.
80 |
81 | Then change directory to the folder 01-getting-started-with-angular2, where you will find a small node project with a `package.json`.
82 |
83 | On the command line run the following:
84 |
85 | npm install
86 |
87 | If you prefer the Yarn package manager, you can also run:
88 |
89 | yarn
90 |
91 | Although npm install would also work, its recommended to use Yarn to install the course dependencies. Yarn has the big advantage that if you use it you will be
92 | installing the exact same dependencies than I installed in my machine, so you wont run into issues caused by semantic versioning updates.
93 |
94 | This should take a couple of minutes. If there are issues, please post the complete error message in the Questions section of the course.
95 |
96 | # Starting the development server
97 |
98 | To start the server, run the following command:
99 |
100 | npm start
101 |
102 | If you now go to [http://localhost:8080](http://localhost:8080), there will be a running application at this url.
103 |
104 | # Making changes
105 |
106 | If you edit a Typescript file and refresh the browser, the changes will be applied.
107 |
108 |
109 | ## Brought to you by the Angular University
110 |
111 | Have a look at our course pipeline at [angular-university.io](https://angular-university.io/).
112 |
113 |
114 |
--------------------------------------------------------------------------------
/theme/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "theme",
3 | "version": "1.0.0",
4 | "description": "Angular Academy Lessons Theme",
5 | "scripts": {
6 | "build": "node-sass -o dist styles/angular-academy-lessons-theme.scss",
7 | "watch": "nodemon -V -w styles --ext \".scss\" --exec \"npm run build\""
8 | },
9 | "devDependencies": {
10 | "node-sass": "^3.5.3"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/theme/styles/angular-academy-lessons-theme.scss:
--------------------------------------------------------------------------------
1 |
2 | @import "vendors/normalize";
3 | @import "project/fonts";
4 | @import "project/colors";
5 | @import "project/defaults";
6 | @import "project/layout";
7 | @import "project/centering";
8 | @import "project/card";
9 | @import "project/input";
10 | @import "project/tabs";
11 | @import "project/getting_started_lessons";
12 |
13 |
14 |
--------------------------------------------------------------------------------
/theme/styles/project/_card.scss:
--------------------------------------------------------------------------------
1 |
2 | $normal-card-shadow: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);
3 |
4 | .card {
5 | border-radius: 4px;
6 | box-shadow: $normal-card-shadow;
7 | &.hoverable:hover {
8 | box-shadow: 0 1px 16px 0 rgba(0, 0, 0, .2), 0 2px 8px 0 rgba(0, 0, 0, .14), 0 4px 8px -1px rgba(0, 0, 0, .12)
9 | }
10 | }
11 |
12 | .card.card-strong {
13 | box-shadow: 0 1px 16px 0 rgba(0, 0, 0, .2), 0 2px 8px 0 rgba(0, 0, 0, .14), 0 4px 8px -1px rgba(0, 0, 0, .12);
14 | &.hoverable:hover {
15 | box-shadow: 0 2px 32px 0 rgba(0, 0, 0, .2), 0 4px 16px 0 rgba(0, 0, 0, .14), 0 8px 16px -2px rgba(0, 0, 0, .12)
16 | }
17 | }
18 |
19 | .card
20 |
21 |
22 | .card-header {
23 | background: $primary;
24 | color: white;
25 | border-top-left-radius: 4px;
26 | border-top-right-radius: 4px;
27 | text-align: left;
28 | height: 48px;
29 | box-sizing: border-box;
30 | line-height: 48px;
31 | padding: 0 12px;
32 |
33 | }
34 |
35 | .card-body {
36 | padding:24px 12px;
37 | }
38 |
--------------------------------------------------------------------------------
/theme/styles/project/_centering.scss:
--------------------------------------------------------------------------------
1 |
2 |
3 | .v-center-parent {
4 | position: relative;
5 | }
6 |
7 | .v-center {
8 | position: absolute;
9 | top: 50%;
10 | transform: translateY(-50%);
11 | }
12 |
13 | .h-center-parent {
14 | position: relative;
15 | }
16 |
17 | .h-center {
18 | position: absolute;
19 | left: 50%;
20 | transform: translateX(-50%);
21 | }
22 |
23 | .v-h-center-parent {
24 | position: relative;
25 | }
26 |
27 | .v-h-center {
28 | position: absolute;
29 | top: 50%;
30 | left: 50%;
31 | transform: translateX(-50%) translateY(-50%);
32 | }
33 |
--------------------------------------------------------------------------------
/theme/styles/project/_colors.scss:
--------------------------------------------------------------------------------
1 |
2 | $page-background: #FAFAFA;
3 |
4 | $primary: rgb(25, 118, 210);
5 | $primary-tint-1: #3F94E9;
6 |
7 | $secondary: rgba(0, 0, 0, 0.117647);
8 |
9 |
10 | $text:rgba(26, 35, 38, 0.8);
11 |
12 | $primary-contrast: white;
13 |
14 | $error-text: #a94442;
15 |
--------------------------------------------------------------------------------
/theme/styles/project/_defaults.scss:
--------------------------------------------------------------------------------
1 |
2 | $unit: 24px;
3 |
4 | body {
5 | font-family: $Roboto;
6 | font-weight: 400;
7 | font-style: normal;
8 | font-size: $h5;
9 | line-height: $unit;
10 | margin: 0;
11 | -webkit-font-smoothing: antialiased;
12 | -moz-osx-font-smoothing: grayscale;
13 | background: $page-background;
14 | color: $text;
15 |
16 | }
17 |
18 |
19 |
--------------------------------------------------------------------------------
/theme/styles/project/_fonts.scss:
--------------------------------------------------------------------------------
1 |
2 | $Roboto: "Roboto", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
3 |
4 | $h0: 67px;
5 | $h1: 50px;
6 | $h2: 37px;
7 | $h3: 28px;
8 | $h4: 21px;
9 | $h5: 16px;
10 | $h6: 12px;
11 | $h7: 9px;
12 | $h8: 7px;
13 | $h9: 5px;
14 |
15 |
--------------------------------------------------------------------------------
/theme/styles/project/_getting_started_lessons.scss:
--------------------------------------------------------------------------------
1 |
2 |
3 | .lesson-1 {
4 | min-height: 200px;
5 | padding-top: 70px;
6 | input {
7 | margin-right: 5px;
8 | }
9 | }
--------------------------------------------------------------------------------
/theme/styles/project/_input.scss:
--------------------------------------------------------------------------------
1 | input {
2 | $height: 28px;
3 | cursor: text;
4 | box-sizing: border-box;
5 | background: white;
6 | outline: none;
7 | border: 1px solid #cccccc;
8 | width: 175px;
9 | height: $height;
10 | line-height: $height;
11 | padding-left: 3px;
12 | box-shadow: inset 0 1px 3px #e6e6e6;
13 | border-radius: 3px;
14 | }
15 |
16 | input:focus {
17 | border-color: #129FEA;
18 | box-shadow: 0 0 5px rgba(102, 175, 233, 0.6);
19 | }
20 |
21 | .ng-touched.ng-invalid {
22 | border: 1px solid $error-text;
23 | }
--------------------------------------------------------------------------------
/theme/styles/project/_layout.scss:
--------------------------------------------------------------------------------
1 |
2 | .l-header {
3 | $height: 2*$unit;
4 | background: $primary;
5 | color: $primary-contrast;
6 | height: $height;
7 | line-height: $height;
8 | vertical-align: middle;
9 | padding-left: 0.5 * $unit;
10 | margin-bottom: 40px;
11 |
12 | img {
13 | height: 40px;
14 | }
15 |
16 | .title {
17 | font-size: $h4;
18 | margin-left: 50px;
19 | }
20 |
21 | .l-header-url {
22 | margin-left: 35px;
23 | }
24 | }
25 |
26 | .l-course-logo {
27 | height:240px;
28 | margin: 0 auto;
29 | background-color: $page-background;
30 | background-image: url(https://material.angularjs.org/latest/img/icons/angular-logo.svg);
31 | background-repeat: no-repeat;
32 | background-position-x: center;
33 | background-size: 65px;
34 | background-position-y: center;
35 | }
36 |
37 |
38 | .l-course-title {
39 | text-align: center;
40 | font-size: $h5;
41 | }
42 |
43 | .l-lesson-title {
44 | text-align: center;
45 | font-size: $h6;
46 | }
47 |
48 | .l-course-content {
49 | margin: 47px auto;
50 | max-width: 400px;
51 | box-sizing: border-box;
52 | padding: 50px;
53 | min-height: 200px;
54 | }
--------------------------------------------------------------------------------
/theme/styles/project/_tabs.scss:
--------------------------------------------------------------------------------
1 |
2 |
3 | .tab-container {
4 |
5 | $tab-border: 1px solid $secondary;
6 |
7 | .tab-buttons {
8 |
9 | list-style: none;
10 | text-align: left;
11 | margin-bottom: 0;
12 | padding: 7px 0 0 10px;
13 | background: $primary;
14 | border-top-left-radius: 4px;
15 | border-top-right-radius: 4px;
16 |
17 | li {
18 | display: inline-block;
19 | color: white;
20 | background: $primary-tint-1;
21 | font-size: $h6;
22 | padding: 2px 20px;
23 | cursor: pointer;
24 | border-top-left-radius: 4px;
25 | border-top-right-radius: 4px;
26 | border-top: $tab-border;
27 | border-left: $tab-border;
28 | border-right: $tab-border;
29 | margin-right: 5px;
30 |
31 | &.selected {
32 | background: white;
33 | color:$text;
34 | border-bottom: 1px solid white;
35 | }
36 |
37 | }
38 | }
39 |
40 | .tab-panel {
41 | border-left: $tab-border;
42 | border-right: $tab-border;
43 | border-bottom: $tab-border;
44 | }
45 |
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/theme/styles/vendors/_normalize.scss:
--------------------------------------------------------------------------------
1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */
2 |
3 | /**
4 | * 1. Set default font family to sans-serif.
5 | * 2. Prevent iOS text size adjust after orientation change, without disabling
6 | * user zoom.
7 | */
8 |
9 | html {
10 | font-family: sans-serif; /* 1 */
11 | -ms-text-size-adjust: 100%; /* 2 */
12 | -webkit-text-size-adjust: 100%; /* 2 */
13 | }
14 |
15 | /**
16 | * Remove default margin.
17 | */
18 |
19 | body {
20 | margin: 0;
21 | }
22 |
23 | /* HTML5 display definitions
24 | ========================================================================== */
25 |
26 | /**
27 | * Correct `block` display not defined for any HTML5 element in IE 8/9.
28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11
29 | * and Firefox.
30 | * Correct `block` display not defined for `main` in IE 11.
31 | */
32 |
33 | article,
34 | aside,
35 | details,
36 | figcaption,
37 | figure,
38 | footer,
39 | header,
40 | hgroup,
41 | main,
42 | menu,
43 | nav,
44 | section,
45 | summary {
46 | display: block;
47 | }
48 |
49 | /**
50 | * 1. Correct `inline-block` display not defined in IE 8/9.
51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
52 | */
53 |
54 | audio,
55 | canvas,
56 | progress,
57 | video {
58 | display: inline-block; /* 1 */
59 | vertical-align: baseline; /* 2 */
60 | }
61 |
62 | /**
63 | * Prevent modern browsers from displaying `audio` without controls.
64 | * Remove excess height in iOS 5 devices.
65 | */
66 |
67 | audio:not([controls]) {
68 | display: none;
69 | height: 0;
70 | }
71 |
72 | /**
73 | * Address `[hidden]` styling not present in IE 8/9/10.
74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
75 | */
76 |
77 | [hidden],
78 | template {
79 | display: none;
80 | }
81 |
82 | /* Links
83 | ========================================================================== */
84 |
85 | /**
86 | * Remove the gray background color from active links in IE 10.
87 | */
88 |
89 | a {
90 | background-color: transparent;
91 | }
92 |
93 | /**
94 | * Improve readability when focused and also mouse hovered in all browsers.
95 | */
96 |
97 | a:active,
98 | a:hover {
99 | outline: 0;
100 | }
101 |
102 | /* Text-level semantics
103 | ========================================================================== */
104 |
105 | /**
106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
107 | */
108 |
109 | abbr[title] {
110 | border-bottom: 1px dotted;
111 | }
112 |
113 | /**
114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
115 | */
116 |
117 | b,
118 | strong {
119 | font-weight: bold;
120 | }
121 |
122 | /**
123 | * Address styling not present in Safari and Chrome.
124 | */
125 |
126 | dfn {
127 | font-style: italic;
128 | }
129 |
130 | /**
131 | * Address variable `h1` font-size and margin within `section` and `article`
132 | * contexts in Firefox 4+, Safari, and Chrome.
133 | */
134 |
135 | h1 {
136 | font-size: 2em;
137 | margin: 0.67em 0;
138 | }
139 |
140 | /**
141 | * Address styling not present in IE 8/9.
142 | */
143 |
144 | mark {
145 | background: #ff0;
146 | color: #000;
147 | }
148 |
149 | /**
150 | * Address inconsistent and variable font size in all browsers.
151 | */
152 |
153 | small {
154 | font-size: 80%;
155 | }
156 |
157 | /**
158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
159 | */
160 |
161 | sub,
162 | sup {
163 | font-size: 75%;
164 | line-height: 0;
165 | position: relative;
166 | vertical-align: baseline;
167 | }
168 |
169 | sup {
170 | top: -0.5em;
171 | }
172 |
173 | sub {
174 | bottom: -0.25em;
175 | }
176 |
177 | /* Embedded content
178 | ========================================================================== */
179 |
180 | /**
181 | * Remove border when inside `a` element in IE 8/9/10.
182 | */
183 |
184 | img {
185 | border: 0;
186 | }
187 |
188 | /**
189 | * Correct overflow not hidden in IE 9/10/11.
190 | */
191 |
192 | svg:not(:root) {
193 | overflow: hidden;
194 | }
195 |
196 | /* Grouping content
197 | ========================================================================== */
198 |
199 | /**
200 | * Address margin not present in IE 8/9 and Safari.
201 | */
202 |
203 | figure {
204 | margin: 1em 40px;
205 | }
206 |
207 | /**
208 | * Address differences between Firefox and other browsers.
209 | */
210 |
211 | hr {
212 | -moz-box-sizing: content-box;
213 | box-sizing: content-box;
214 | height: 0;
215 | }
216 |
217 | /**
218 | * Contain overflow in all browsers.
219 | */
220 |
221 | pre {
222 | overflow: auto;
223 | }
224 |
225 | /**
226 | * Address odd `em`-unit font size rendering in all browsers.
227 | */
228 |
229 | code,
230 | kbd,
231 | pre,
232 | samp {
233 | font-family: monospace, monospace;
234 | font-size: 1em;
235 | }
236 |
237 | /* Forms
238 | ========================================================================== */
239 |
240 | /**
241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited
242 | * styling of `select`, unless a `border` property is set.
243 | */
244 |
245 | /**
246 | * 1. Correct color not being inherited.
247 | * Known issue: affects color of disabled elements.
248 | * 2. Correct font properties not being inherited.
249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
250 | */
251 |
252 | button,
253 | input,
254 | optgroup,
255 | select,
256 | textarea {
257 | color: inherit; /* 1 */
258 | font: inherit; /* 2 */
259 | margin: 0; /* 3 */
260 | }
261 |
262 | /**
263 | * Address `overflow` set to `hidden` in IE 8/9/10/11.
264 | */
265 |
266 | button {
267 | overflow: visible;
268 | }
269 |
270 | /**
271 | * Address inconsistent `text-transform` inheritance for `button` and `select`.
272 | * All other form control elements do not inherit `text-transform` values.
273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
274 | * Correct `select` style inheritance in Firefox.
275 | */
276 |
277 | button,
278 | select {
279 | text-transform: none;
280 | }
281 |
282 | /**
283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
284 | * and `video` controls.
285 | * 2. Correct inability to style clickable `input` types in iOS.
286 | * 3. Improve usability and consistency of cursor style between image-type
287 | * `input` and others.
288 | */
289 |
290 | button,
291 | html input[type="button"], /* 1 */
292 | input[type="reset"],
293 | input[type="submit"] {
294 | -webkit-appearance: button; /* 2 */
295 | cursor: pointer; /* 3 */
296 | }
297 |
298 | /**
299 | * Re-set default cursor for disabled elements.
300 | */
301 |
302 | button[disabled],
303 | html input[disabled] {
304 | cursor: default;
305 | }
306 |
307 | /**
308 | * Remove inner padding and border in Firefox 4+.
309 | */
310 |
311 | button::-moz-focus-inner,
312 | input::-moz-focus-inner {
313 | border: 0;
314 | padding: 0;
315 | }
316 |
317 | /**
318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in
319 | * the UA stylesheet.
320 | */
321 |
322 | input {
323 | line-height: normal;
324 | }
325 |
326 | /**
327 | * It's recommended that you don't attempt to style these elements.
328 | * Firefox's implementation doesn't respect box-sizing, padding, or width.
329 | *
330 | * 1. Address box sizing set to `content-box` in IE 8/9/10.
331 | * 2. Remove excess padding in IE 8/9/10.
332 | */
333 |
334 | input[type="checkbox"],
335 | input[type="radio"] {
336 | box-sizing: border-box; /* 1 */
337 | padding: 0; /* 2 */
338 | }
339 |
340 | /**
341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain
342 | * `font-size` values of the `input`, it causes the cursor style of the
343 | * decrement button to change from `default` to `text`.
344 | */
345 |
346 | input[type="number"]::-webkit-inner-spin-button,
347 | input[type="number"]::-webkit-outer-spin-button {
348 | height: auto;
349 | }
350 |
351 | /**
352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
354 | * (include `-moz` to future-proof).
355 | */
356 |
357 | input[type="search"] {
358 | -webkit-appearance: textfield; /* 1 */
359 | -moz-box-sizing: content-box;
360 | -webkit-box-sizing: content-box; /* 2 */
361 | box-sizing: content-box;
362 | }
363 |
364 | /**
365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X.
366 | * Safari (but not Chrome) clips the cancel button when the search input has
367 | * padding (and `textfield` appearance).
368 | */
369 |
370 | input[type="search"]::-webkit-search-cancel-button,
371 | input[type="search"]::-webkit-search-decoration {
372 | -webkit-appearance: none;
373 | }
374 |
375 | /**
376 | * Define consistent border, margin, and padding.
377 | */
378 |
379 | fieldset {
380 | border: 1px solid #c0c0c0;
381 | margin: 0 2px;
382 | padding: 0.35em 0.625em 0.75em;
383 | }
384 |
385 | /**
386 | * 1. Correct `color` not being inherited in IE 8/9/10/11.
387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets.
388 | */
389 |
390 | legend {
391 | border: 0; /* 1 */
392 | padding: 0; /* 2 */
393 | }
394 |
395 | /**
396 | * Remove default vertical scrollbar in IE 8/9/10/11.
397 | */
398 |
399 | textarea {
400 | overflow: auto;
401 | }
402 |
403 | /**
404 | * Don't inherit the `font-weight` (applied by a rule above).
405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
406 | */
407 |
408 | optgroup {
409 | font-weight: bold;
410 | }
411 |
412 | /* Tables
413 | ========================================================================== */
414 |
415 | /**
416 | * Remove most spacing between table cells.
417 | */
418 |
419 | table {
420 | border-collapse: collapse;
421 | border-spacing: 0;
422 | }
423 |
424 | td,
425 | th {
426 | padding: 0;
427 | }
--------------------------------------------------------------------------------