Skip to content

Commit 070a2c9

Browse files
committed
Milestone #3
1 parent 964e693 commit 070a2c9

6 files changed

+160
-175
lines changed

src/app/demo/bootstrap/bootstrap.component.html

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -162,63 +162,4 @@ <h3>
162162
<app-code-editor [fontSize]="15" [code]="code.moduleBootstrapping.code.indexHTML"></app-code-editor>
163163
</app-slide>
164164

165-
166-
<!-- MILESTONE #3 Dependency Injection-->
167-
<!-- RECAP -->
168-
<app-slide>
169-
<h1 style="text-align: center;">Recap</h1>
170-
<h2>
171-
<b>Dependency Injection</b> is a way to provide dependencies to your code instead of hard-coding them.
172-
</h2>
173-
</app-slide>
174-
175-
<!-- COMPARISON -->
176-
<app-slide>
177-
<h1>Comparison</h1>
178-
<div class="content-container">
179-
<div class="col-6 card">
180-
<h3 style="text-align: center;">Without Dependency Injection</h3>
181-
<!--<app-editor [file]="code.component.noDependencyInjection" [fontSize]="15"-->
182-
<!--[app-focus-highlight-match]="[code.component.noDependencyInjection.match]"></app-editor>-->
183-
</div>
184-
<div class="col-6 card" style="margin-left: 10px;">
185-
<h3 style="text-align: center;">With Dependency Injection</h3>
186-
<!--<app-editor [file]="code.component.dependencyInjection" [fontSize]="15"-->
187-
<!--[app-focus-highlight-match]="[code.component.dependencyInjection.match]"></app-editor>-->
188-
</div>
189-
</div>
190-
</app-slide>
191-
192-
<!-- IMPLEMENTATION STEP #1-->
193-
<app-slide>
194-
<h1>Implementation Step #1</h1>
195-
<h2>Mark a class as a Injectable</h2>
196-
<!--<app-editor [file]="code.injectable.classAsInjectable" [fontSize]="30"-->
197-
<!--[app-focus-highlight-match]="[code.injectable.classAsInjectable.match]"></app-editor>-->
198-
</app-slide>
199-
200-
<!-- IMPLEMENTATION STEP #2-->
201-
<app-slide>
202-
<h1>Implementation Step #2</h1>
203-
<h2>Provide the injectable</h2>
204-
<!--<app-editor [file]="code.injectable.provideTheInjectable" [fontSize]="30"-->
205-
<!--[app-focus-highlight-match]="[code.injectable.provideTheInjectable.match]"></app-editor>-->
206-
</app-slide>
207-
208-
<!-- IMPLEMENTATION STEP #3-->
209-
<app-slide>
210-
<h1>Implementation Step #3</h1>
211-
<h2>Consume the Injectable</h2>
212-
<!--<app-editor [file]="code.component.consumeTheInjectable" [fontSize]="30"-->
213-
<!--[app-focus-highlight-match]="[code.component.consumeTheInjectable.match]"></app-editor>-->
214-
</app-slide>
215-
216-
<!-- HANDLING SERVICES-->
217-
<app-slide>
218-
<h1>Handling services</h1>
219-
<h2>Promises and callbacks</h2>
220-
<!--<app-editor [file]="code.component.handlingServices" [fontSize]="15"-->
221-
<!--[app-focus-highlight-match]="[code.component.handlingServices.match]"></app-editor>-->
222-
</app-slide>
223-
224165
</app-presentation>

src/app/demo/bootstrap/bootstrap.component.ts

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class AppModule {}`,
4949
path: 'module.anatomy.ts',
5050
type: 'typescript'
5151
},
52-
moduleBootstrapping: {
52+
moduleBootstrapping: { // Module Bootstraping - Milestone #1
5353
code: {
5454
mainTs: `import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
5555
import { AppModule } from './app.module';
@@ -121,20 +121,6 @@ export class AppComponent {
121121
"code": "import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';\nimport {AppModule} from './app.module';\n\nconst platform = platformBrowserDynamic();\nplatform.bootstrapModule(AppModule);\n",
122122
"readonly": true,
123123
"collapsed": true
124-
},
125-
{
126-
"bootstrap": true,
127-
"excludeFromTesting": false,
128-
"type": "typescript",
129-
"path": "tests/test.ts",
130-
"template": "\nimport {TestBed} from '@angular/core/testing';\n// Solution prefix will be stripped-out by the app\nimport {AppComponent, evalJs} from '../app.component';\nimport 'reflect-metadata';\n\nlet metadata;\nbeforeEach(() => {\n try {\n TestBed.resetTestingModule();\n TestBed.configureTestingModule({declarations: [AppComponent]});\n metadata = Reflect.getMetadata('annotations', AppComponent);\n } catch (e) {\n // Do nothing, we have assertions below for this case\n }\n});\n\ndescribe('Component', () => {\n it(`Create a class called AppComponent`, () => {\n chai.expect(typeof evalJs('AppComponent')).equals('function');\n });\n\n it(`Export the created class`, () => {\n chai.expect(typeof AppComponent).equals('function');\n });\n\n it(`Add a Component decorator for the class`, () => {\n chai.expect(metadata).is.not.undefined\n });\n\n it(`Add a selector to the component decorator`, () => {\n chai.expect(metadata[0].selector).equals('my-app');\n });\n\n it(`Add a template that contains: '<h1>Hello CatTube!</h1>'`, () => {\n chai.expect(metadata[0].template).equals('<h1>Hello CatTube!</h1>');\n });\n});\n\n",
131-
"moduleName": "tests/test",
132-
"code": "\nimport {TestBed} from '@angular/core/testing';\n// Solution prefix will be stripped-out by the app\nimport {AppComponent, evalJs} from '../app.component';\nimport 'reflect-metadata';\n\nlet metadata;\nbeforeEach(() => {\n try {\n TestBed.resetTestingModule();\n TestBed.configureTestingModule({declarations: [AppComponent]});\n metadata = Reflect.getMetadata('annotations', AppComponent);\n } catch (e) {\n // Do nothing, we have assertions below for this case\n }\n});\n\ndescribe('Component', () => {\n it(`Create a class called AppComponent`, () => {\n chai.expect(typeof evalJs('AppComponent')).equals('function');\n });\n\n it(`Export the created class`, () => {\n chai.expect(typeof AppComponent).equals('function');\n });\n\n it(`Add a Component decorator for the class`, () => {\n chai.expect(metadata).is.not.undefined\n });\n\n it(`Add a selector to the component decorator`, () => {\n chai.expect(metadata[0].selector).equals('my-app');\n });\n\n it(`Add a template that contains: '<h1>Hello CatTube!</h1>'`, () => {\n chai.expect(metadata[0].template).equals('<h1>Hello CatTube!</h1>');\n });\n});\n\n",
133-
"solution": "\nimport {TestBed} from '@angular/core/testing';\n// Solution prefix will be stripped-out by the app\nimport {AppComponent, evalJs} from '../app.component';\nimport 'reflect-metadata';\n\nlet metadata;\nbeforeEach(() => {\n try {\n TestBed.resetTestingModule();\n TestBed.configureTestingModule({declarations: [AppComponent]});\n metadata = Reflect.getMetadata('annotations', AppComponent);\n } catch (e) {\n // Do nothing, we have assertions below for this case\n }\n});\n\ndescribe('Component', () => {\n it(`Create a class called AppComponent`, () => {\n chai.expect(typeof evalJs('AppComponent')).equals('function');\n });\n\n it(`Export the created class`, () => {\n chai.expect(typeof AppComponent).equals('function');\n });\n\n it(`Add a Component decorator for the class`, () => {\n chai.expect(metadata).is.not.undefined\n });\n\n it(`Add a selector to the component decorator`, () => {\n chai.expect(metadata[0].selector).equals('my-app');\n });\n\n it(`Add a template that contains: '<h1>Hello CatTube!</h1>'`, () => {\n chai.expect(metadata[0].template).equals('<h1>Hello CatTube!</h1>');\n });\n});\n\n",
134-
"test": true,
135-
"before": "mochaBefore();",
136-
"after": "mochaAfter();",
137-
"hidden": true
138124
}
139125
]
140126
}

src/app/demo/demo/demo.component.ts

Lines changed: 0 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -34,74 +34,6 @@ export class AppComponent {
3434
type: 'typescript',
3535

3636
},
37-
consumeTheInjectable:{
38-
code: `import { Component } from '@angular/core';
39-
import { UnitConverterService }
40-
from '../services/unit-converter.service';
41-
42-
@Component({...})
43-
export class UnitConversionComponent {
44-
constructor(converter: UnitConverterService) {}
45-
}`,
46-
readonly: true,
47-
path: 'unit-conversion.component.ts',
48-
type: 'typescript',
49-
match: /constructor.*/
50-
},
51-
handlingServices:{
52-
code: `import { Component } from '@angular/core';
53-
import { UnitConverterService }
54-
from '../services/unit-converter.service';
55-
56-
@Component({...})
57-
export class UnitConversionComponent {
58-
constructor(converter: UnitConverterService) {}
59-
getUnit(fromUnit: string, value: number) {
60-
this.converter.doStuff();
61-
}
62-
}`,
63-
readonly: true,
64-
path: 'unit-conversion.getUnit.component.ts',
65-
type: 'typescript',
66-
match: /getUnit[^]*?\)[^]/
67-
},
68-
moduleBootstrapping:{
69-
code: `import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
70-
import { AppModule } from './app.module';
71-
72-
platformBrowserDynamic().bootstrapModule(AppModule);`,
73-
readonly: true,
74-
path: 'main-bootstrap.ts',
75-
type: 'typescript'
76-
},
77-
noDependencyInjection: {
78-
code: `export class Person {
79-
profession: Profession;
80-
81-
constructor(name: string, age: number) {
82-
this.profession = new Profession();
83-
}
84-
85-
}`,
86-
readonly: true,
87-
path: 'person.noDI.ts',
88-
type: 'typescript',
89-
match: /this.*/
90-
},
91-
92-
dependencyInjection: {
93-
code: `export class MyComponent {
94-
/**
95-
* Typescript shorthand makes 'service'
96-
* available to component instance.
97-
*/
98-
constructor(public service: MyService) {}
99-
}`,
100-
readonly: true,
101-
path: 'person.module.ts',
102-
type: 'typescript',
103-
match: /constructor.*/
104-
},
10537
'test1': {
10638
code: `import {Hello} from 'Hello';
10739
console.log(new Hello(2016).hello())`,
@@ -116,37 +48,6 @@ console.log(new Hello(2016).hello())`,
11648
fontSize: 40 //optional
11749
}
11850
];`
119-
},
120-
injectable: {
121-
classAsInjectable: {
122-
code: `import { Injectable } from '@angular/core';
123-
124-
@Injectable()
125-
export class MyService {
126-
...
127-
}`,
128-
readonly: true,
129-
path: 'my-service.ts',
130-
type: 'typescript',
131-
match: /@I[^]*?\)[^]/
132-
},
133-
provideTheInjectable:{
134-
code: `import { NgModule } from '@angular/core';
135-
import { UnitConverterService }
136-
from '../services/unit-converter.service';
137-
import { UnitConversionComponent }
138-
from './unit-conversion.component';
139-
140-
@NgModule({
141-
declarations: [ UnitConversionComponent ],
142-
providers: [ UnitConverterService ],
143-
})
144-
export class AppModule {}`,
145-
readonly: true,
146-
path: 'injectable.app.module.ts',
147-
type: 'typescript',
148-
match: /providers.*/
149-
}
15051
}
15152
};
15253
exercises = [
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.content-container{
2+
display: flex;
3+
flex-direction: row;
4+
width: 100%;
5+
margin-top: 20px;
6+
}
Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,80 @@
11
<app-presentation app-slides-routing>
22
<app-progress-bar></app-progress-bar>
33
<app-arrows></app-arrows>
4-
<app-slide>DI 1</app-slide>
5-
<app-slide>DI 2</app-slide>
4+
5+
<!-- MILESTONE #3 Dependency Injection -->
6+
<!-- RECAP -->
7+
<app-slide>
8+
<h1 style="text-align: center;">Recap</h1>
9+
<h2>
10+
<b>Dependency Injection</b> is a way to provide dependencies to your code instead of hard-coding them.
11+
</h2>
12+
</app-slide>
13+
14+
<!-- COMPARISON -->
15+
<app-slide>
16+
<h1>Comparison</h1>
17+
<div class="content-container">
18+
<div class="col-6">
19+
<h3 style="text-align: justify;">Without Dependency Injection</h3>
20+
<app-code-editor [fontSize]="15" [code]="code.withOutDI.code"
21+
[focus-highlight-match]="[code.withOutDI.matches.noDI, 'profession']"></app-code-editor>
22+
<ul style="margin-top: 10px; text-align: justify;">
23+
<li>The Person class creates everything it needs inside its constructor.</li>
24+
<li>The Person class is brittle, inflexible, and hard to test.</li>
25+
<li>This Person needs a profession. Instead of asking for it, the Person constructor
26+
instantiates its own copy from the very specific class Profession.</li>
27+
<li>If the Profession class evolve and requires a parameter, we will break the Person class.</li>
28+
<li>You have no control over the person's hidden dependencies.</li>
29+
</ul>
30+
</div>
31+
<div class="col-6" style="margin-left: 10px;">
32+
<h3 style="text-align: center;">With Dependency Injection</h3>
33+
<app-code-editor [fontSize]="15" [code]="code.withDI.code"
34+
[focus-highlight-match]="[code.withDI.matches.constructor]"></app-code-editor>
35+
<ul style="margin-top: 10px; text-align: justify;">
36+
<li>The Person class no longer creates a profession. It just consume it.</li>
37+
<li>If someone extends the Profession class, it is not a Person's problem.</li>
38+
<li>You have complete control of Person's dependencies.</li>
39+
</ul>
40+
</div>
41+
</div>
42+
</app-slide>
43+
44+
<!-- IMPLEMENTATION STEP #1 -->
45+
<app-slide>
46+
<h1>Implementation Step #1</h1>
47+
<h2>Mark a class as Injectable</h2>
48+
<app-code-editor [fontSize]="15" [code]="code.classAsInjectable.code"
49+
[focus-highlight-match]="[code.classAsInjectable.matches.injectable]"></app-code-editor>
50+
</app-slide>
51+
52+
<!-- IMPLEMENTATION STEP #2 -->
53+
<app-slide>
54+
<h1>Implementation Step #2</h1>
55+
<h2>Provide the injectable</h2>
56+
<app-code-editor [fontSize]="15" [code]="code.provideInjectable.code"
57+
[focus-highlight-match]="[code.provideInjectable.matches.providers, 'UnitConverterService']"></app-code-editor>
58+
</app-slide>
59+
60+
<!-- IMPLEMENTATION STEP #3 -->
61+
<app-slide>
62+
<h1>Implementation Step #3</h1>
63+
<h2>Consume the Injectable</h2>
64+
<app-code-editor [fontSize]="15" [code]="code.consumeInjectable.code"
65+
[focus-highlight-match]="[code.consumeInjectable.matches.constructor]"></app-code-editor>
66+
</app-slide>
67+
68+
<!-- HANDLING SERVICES PROMISES -->
69+
<app-slide>
70+
<h1>Handling services</h1>
71+
<h2>Promises and callbacks</h2>
72+
</app-slide>
73+
74+
<!-- HANDLING SERVICES OBSERVABLES -->
75+
<app-slide>
76+
<h1>Handling services</h1>
77+
<h2>Observables and callbacks</h2>
78+
</app-slide>
679

780
</app-presentation>

src/app/demo/dependency-injection/dependency-injection.component.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,83 @@ import {BaseRouteableComponent} from '../BaseRouteableComponent';
88
})
99
export class DependencyInjectionComponent extends BaseRouteableComponent {
1010

11+
code = {
12+
withOutDI: {
13+
code: `export class Person {
14+
profession: Profession;
15+
16+
constructor() {
17+
this.profession = new Profession();
18+
}
19+
20+
}`,
21+
matches: {
22+
noDI: /this.*/
23+
},
24+
readonly: true,
25+
path: 'person-noDI.ts',
26+
type: 'typescript'
27+
},
28+
29+
withDI: {
30+
code: `export class Person {
31+
/**
32+
* Typescript shorthand makes 'profession'
33+
* available to component instance.
34+
*/
35+
constructor(public profession: Profession) {}
36+
}`,
37+
matches: {
38+
constructor: /constructor.*/
39+
},
40+
readonly: true,
41+
path: 'personDI.ts',
42+
type: 'typescript'
43+
},
44+
45+
classAsInjectable: {
46+
code: `import { Injectable } from '@angular/core';
47+
48+
@Injectable()
49+
export class MyService {
50+
...
51+
}`,
52+
matches: {
53+
injectable: /@I[^]*?\)[^]/
54+
},
55+
readonly: true,
56+
type: 'typescript'
57+
},
58+
59+
provideInjectable: {
60+
code: `import { NgModule } from '@angular/core';
61+
import { UnitConverterService } from '../services/unit-converter.service';
62+
import { UnitConversionComponent } from './unit-conversion.component';
63+
64+
@NgModule({
65+
declarations: [ UnitConversionComponent ],
66+
providers: [ UnitConverterService ],
67+
})
68+
export class AppModule {}`,
69+
matches: {
70+
providers: /providers.*/
71+
},
72+
readonly: true,
73+
type: 'typescript'
74+
},
75+
76+
consumeInjectable: {
77+
code: `import { Component } from '@angular/core';
78+
import { UnitConverterService } from '../services/unit-converter.service';
79+
80+
@Component({...})
81+
export class UnitConversionComponent {
82+
constructor(converter: UnitConverterService) {}
83+
}`,
84+
matches: {
85+
constructor: /constructor.*/
86+
}
87+
}
88+
};
1189

1290
}

0 commit comments

Comments
 (0)