-
Notifications
You must be signed in to change notification settings - Fork 0
/
notes
313 lines (244 loc) · 14.7 KB
/
notes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
custom-assets folder has Screenshot of Manual setting up of Angular application
or use angular get started project by
github.com/angular/quickstart
(OR) Angular cli - for generating set of files and boilerplate code, generates modules, components, services and tests are included, and packages for deployment
(OR) github.com/DeborahK/Angular-GettingStarted - APM-Start
Angular CLI uses webpack - so all of ts files are listed in webpack node
set a breakpoint in ts file
npm start - runs 'ng' , ng executes the angular cli, string after ng is the cli command
ng serve -o : runs the webserver and opens in browser
angular cli - creates root component
javascript namespaces - variables/func in global namespace
use modules to resolve problems of namespaces
angularjs has modules
typescript has modules
es2015 - a module is a file, a file is a module
Angular: leverages es2015 modules, we create modules for apps, angular also has angular modules (diff impl of es2015)
es2015 modules
export and import
export class Product{} - product.ts
import { Product } from './product' - product-list.ts
both above are modules
when we compile the ts is transpiled into es2015 .js file
angular modules helps for cohesive block of functionality (Components)
each feature is a module
shared/common module used by multiple module - to load on start or lazy load
atleast one module, called @module
each angular module we declare set of components associated with module
custom-assets folder has Screenshots of ES Modules vs Angular modules
Component: It is a combination of
Templates (: View layout, using html, includes bindings and directives)
+ Class (associated code Properties and methods, using typescript)
+ Metadata (extra data, defined with a decorator, decorator: is a function that adds metadata to a class, its members or arguments)
//this is an es module
export class AppComponent { - feature is the class component name, AppComponent is the root component in general
pageTitle: string = 'Angular2 Product Management'
}
methods are defined after all properties in class
Metadata: Component also has metadata which is defined with decorator. A decorator is a function that adds properties to the class (usually a TS function)
is declared with @ symbol, we can create our own metadata as well.
@Component is Angular component function
declare the decorator above the class signature of the feature
decorator is a function so (), and pass object using {}
this syntax is similar to attributes
@Component({ - @ to identify class as component
selector: 'pm-root', // to reference this component in any html, selector defines the components directive name
//whenever this directive is used in html, angular renders this components template
template: `
<h1>
{{pageTitle}}
</h1>
`
})
Importing: To use an external function we define where to use it, allows to use exported members from other modules
import { Component } from '@angular/core' //component is the decarator used
Bootstrapping:
Tell angular to load root component through bootstrapping which includes:
Setup index.html to host application
define angular module to bootstrap root component
index.html - one true webpage of app, hence SPA (insert bits of html into index.html)
angular compiler knows custom html element (directive)
looks into angular module -
Angular Module:
provides organization to achieve cohesive blocks of functionality
Boundaries: boundaries within our app
Template Resolution environment:
See Screenshot of AppModule arrows
Angular Compiler sees a directive in a template it looks in angular module for the definition
so we declare AppComponent in Angular Module so that the compiler can find it
We also use the angular module to bootstrap our startup (root) component, in this case the app component
Application should now work correctly in browser so import BrowserModule in this angularmodule imports
Defining Angular module: Use @NgModule decorator to identify class as Angular Module and pass the metadata for the angular module
properties include:
declarations : which of components belong to this module, by convention the default AppComponent belongs to this module
bootstrap: Startup component of application (AppComponent)
imports: Define external modules that we want to be available for all of the components that belong to this angular module (BrowserModule : every browser app should register)
declarations: [
AppComponent
]
to tell where the selector is defined
Final Checklist for component
PascalCasing for component name
Metadata defining for component is done using Decorator
A class is not a component unless it has a Component Decorator
selector: is not needed if component is not used in html
inline template : ""
es2015 template: ` `
disadvantages : no automatic formatting and syntax checking in tools
Linked template: templateUrl: url of html file
@Component({
selector: 'pm-products',
templateUrl: './product-list.component.html'
})
Adding components into another component
Using Component as a directive
we can include the (first) component template as directive into second (any) component template by using selector in the former component
if there are 100s of components in the app,
the app looks into angular module that owns this second component defined all of the directives that are visible to the second component
every app has root module
A component must belong to one angular module
App module bootstraps app component and browser module (to run app in browser)
so in this case declare the new first component in the old second components' angular module as below
declarations: [
AppComponent,
ProductListComponent
]
if the new component has its own module we can import the same similar to browser module
Binding: Coordinates comm between class and its template (values from class to template, template raises event back to class)
binding syntax is defined in the template
Intepolation: {{ }} : one way binding : class to template (pageTitle in app-component)
<h1>{{pageTitle}}</h1> === <h1 innerText={{pageTitle}}></h1>
pageTitle - template expression, angular evaluates based on the component in the context
other examples {{2*20+1}} , {{'Title' + getPageTitle()}}
built-in directives : *ngIf, *ngFor,
* - structural directive - modifies the structure or layout of a view by removing or adding elements and their children
ngIf - false - the element and children are removed from DOM, if true - a copy of these are added to DOM
BrowserModule exposes ngIf and ngFor directives, so any component declared by AppModule can use these two structural directives
any[] : any datatype here array
ngFor: repeats one for each item in a list
syntax: *ngFor="let product of products"
not using 'let product in products':
es2015 for loops has both for-of and for-in looop,
for-of is similar to forEach,
for-in loops through the index of the properties
<img [src]='product.imageUrl'> [src] is binding target, value in '' is binding source
binding using Intepolation:
<img src={{product.imageUrl}}>
prefer property binding to interpolation except for a larger expression like 'https://google.com/q={{product.image}}'
ex: <img [src]='product.imageUrl' [title]='product.productName'>
and to set style of width and height, inject these properties in component properties and use property binding as below
[style.width.px] = [image.width], [style.margin.px] = [image.margin]
to perform two way databinding use ngModel as <input [(ngMode)]='listFilter'>
[] = indicates property binding of class property to input element
() = indicates event binding to send notification of user data to class property
to initialize some value in textbox of listFilter, just specify a value for this property in component
ngModel has to be imported in AppModel from 'FormsModel' library
if 'FormsModel' is not imported then the below error on console
"ngModel has to be imported in AppModel from 'FormsModel' library" and add 'FormsModel' in imports array of ngModule decorator
In AppModule.ts
imports array - has directies, components and pipes from other sources including Angular or 3rd parties
declarations array - has our directives, components and pipes
Formatting data - pipes - transform bound properties before they are displayed
built in pipes - date , number, decimal, currency, json, slice - selects a specific elements from list
Custom pipes
{{product.productName | lowercase}}
Multiple pipes : {{product.price | currency | lowercase}}
Parameteric pipes: {{product.price | currency: 'USD' : true : '1.2-2' }}
- true - to display symbol,
1.2-2 - atleast 1 digit to the left of the decimal, atleast 2 digits to the right of the decimal and no more than 2 digits to right of decimal
DATABINDING :
DISPLAY CLASS PROPERTIES FROM COMPONENT
set DOM element properties to class property values
component can listen for events from DOM
Components: What constitutes for a good component
Strong typing & Interface: helps minimize errors with better syntax checking and improved tooling
If no predefined type for property: Define type using interface (like array of Products object which has its own properties and methods)
Encapsulating styles: for components styles are declared inside a component so that they dont affect other components
Lifecycle hooks: Component has a lifecycle managed by Angular. Angular provides lifecycle hooks to tap into key points in that lifecycle adding flexibility and responsiveness to our application
Custom pipes
Nested components
Strong typing and Interface:
In typescript every property has a type , every method has a return type, every method parameter has a type.
In some cases, property or method doesnt have a predefined type such as below products array
products: any[] = [
{
"productId": 1,
"productName": "Leaf Rake",
"productCode": "GDN-0011",
"releaseDate": "March 19, 2016",
"description": "Leaf rake with 48-inch wooden handle.",
"price": 19.95,
"starRating": 3.2,
"imageUrl": "http://openclipart.org/image/300px/svg_to_png/26215/Anonymous_Leaf_Rake.png"
}...
]
To specify custom types, we can define interface
Interface: to declare a related set of methods and properties
A class implements the interface for any business logic pertaining to the component using the interface properties
This interface is then used as a datatype
ES2015 doesnt support interfaces so transpiling doesnt show these in JS, and these interfaces are visbile only in dev.
export Interface IProduct{
productId: number;
productName: string;
releaseDate: string;
calculateDiscount(percent: number): number;
}
the release date can be changed to date type if needed, in future by just changing here
Import the interface and use the interface as datatype
so just replace 'products: any[]' this with 'products: IProduct[]'
Encapsulating Component styles:
External stylesheets are good to use but linking them in index.html will put an extra burden in maintaining and also leaking of styles can occur
Better way: Component decorator has properties to encapsulate styles as part of component definition using
styles : using styles array property - ['thead {color: #2196f3}']
styleUrls: using styleUrls pointing to external style sheets - ['./product-list-component.css'] - this is again array
by doing this within the component, any defined style classes will apply to only the components template without any leaking
Lifecycle: Managed by Angular
Angular creates the component
renders it
creates and renders its children
process changes for any change in data bounding properties
destroys the component before removing from the template
Hooks:
OnInit: Component initialization, retrieve data for template from backend service
OnChanges: Perform action after change to input properties
OnDestroy: to perform clean up before destroys component
implements OnInit - 'angular/core'
ngOnInit(): void{
}
implementing the interface is optional as interfaces are features of typescript and not by es2015 but is a good practice to implement lifecycle hooks
CustomPipe:
Use @Pipe decorator to declare a name for pipe
export a class that implements PipeTransform interface which has transform(),
The syntax is similar to Creating Components
now add it as <td>{{ product.productCode | lowercase | convertToSpaces: '-'}}</td>
but angular cannot find where is convertToSpaces pipe, so the angular module of the component that wants to use this pipe
should have the pipes declaration
Filtering list based on ngmodel : databinding: by using pipe is no longer supported by Angular as the performance of such pipes is poor and prevent
aggressive minification and all of this should be done in component
Nested Components: Adding a component (Child component) inside another container (parent component). The @Input parameters are used to inject
into child components and output is way to read from child components into parent component
the stars width changes based on the rating selected, so the star component implements LifeCycle Hook: OnChanges (look for above definition)
Nested Component:
As a directive:
specify the directive in main container and declare the StarComponent in AngularModule (The module that container that is using StarComponent is using)
<td>{{ product.starRating }}</td> will be changed as
<td><pm-star></pm-star></td>
Passing data to nested components from container:
If a nested component has to recieve inputs from its container it has to expose a property to that container
nested component class should have @Input decorator.
We use @Input To decorate any property in the nested components class to recieve input from its container
@Input() rating: number; - will send rating property to the container so that container can provide the rating number
in container, we use property binding and define nested components (child component) input property as the target of the binding using [] as:
<pm-star [rating]='product.productRating'
Anytime the container data changes, the OnChanges lifecycle event is generated and the property is recalculated
@Output() - if nested component wants to send information back to the container, it can raise an event
to decorate any property of nested component , however the property type must be an event
data to pass becomes the even payload
an event is defined with an event emitter object
EventEmitter<string> = new EventEmitter<string>();
container dom will have name of the event to listen for (from nested components)
<td><pm-star [rating]='product.starRating' (ratingClicked)='onRatingClicked($event)'></pm-star></td>
$event - to access payload from nested component
We can think of @Input and @Output decorators as public api of the nestable components and everything else is encapsulated
Use Property Binding to pass data to the nested components
Use Event binding to respond to events from the nested components