├── README.md
├── images
├── 1.png
├── 2.png
├── 3.png
├── 4.png
├── 5.png
└── 6.png
└── lang
└── README.tr.md
/README.md:
--------------------------------------------------------------------------------
1 | Angular 4 - Notes
2 | ====================
3 |
4 |
5 | This repository is notes of my angular 4 journey. I couldn't switched to ng2. Now I decided to give a shot and getting course about ng4. I will write everthing that I learn, Maybe this repository guide you too.
6 |
7 | Thanks [Maximilian Schwarzmuller](https://www.udemy.com/the-complete-guide-to-angular-2) for great guide.
8 |
9 | Farewell my friend.
10 |
11 | Other Languages
12 | ----------------
13 |
14 | - [Yazıyı türkçe okumak için tıklayın](lang/README.tr.md)
15 |
16 |
17 | Index
18 | ----------------
19 |
20 | - [Installation](#installation)
21 | - [Creating project](#creating-project)
22 | - [Serving project](#serving-project)
23 | - [Investigating created project](#investigating-created-project)
24 | - [Creating a new component](#creating-a-new-component)
25 | - [Create component with cli](#create-component-with-cli)
26 | - [Including bootstrap css to project](#including-bootstrap-css-to-project)
27 | - [Databinding](#databinding)
28 | - [Directives](#directives)
29 | - [ngIf](#ngif)
30 | - [ngFor](#ngfor)
31 | - [ngStyle](#ngstyle)
32 | - [ngClass](#ngclass)
33 | - [ngSwitch](#ngswitch)
34 | - [Input](#input)
35 | - [Output](#output)
36 | - [View Encapsulation](#view-encapsulation)
37 | - [Local Reference](#local-reference)
38 | - [ng-content](#ng-content)
39 | - [Life cycle of components](#life-cycle-of-components)
40 | - [Creating a new directive](#creating-a-new-directive)
41 | - [HostListener](#hostlistener)
42 | - [HostBinding](#hostbinding)
43 | - [Services and dependency injection](#services-and-dependency-injection)
44 | - [Injecting a service into another service](#injecting-a-service-into-another-service)
45 | - [Event emitting service](#event-emitting-service)
46 | - [Router](#router)
47 | - [Links](#links)
48 | - [Active route](#active-route)
49 | - [Navigating from code](#navigating-from-code)
50 | - [Parameters of routes](#parameters-of-routes)
51 | - [Nested routes](#nested-routes)
52 | - [Redirecting](#redirecting)
53 |
54 | ### Installation
55 |
56 | To develop some applications we need to install node.js first. If you didn't know node.js, please check it before ng4. We will use angular cli. Angular cli will help us creating stuff. Its very useful tool.
57 |
58 | ```
59 | npm i @angular/cli -g
60 | ```
61 |
62 | We should install `@angular/cli` with global parameter. This parameter will use global node_modules folder rather than local one.
63 |
64 | Now we can use `ng` command in terminal.
65 |
66 |
67 | ### Creating project
68 |
69 | To create project we will use `ng` command. Try to type `ng` in terminal if you get error then you failed `Installation` step. Please go there and make sure you did this steps right.
70 |
71 | ng command has some more arguments too. We will come to that but rightnow we just have to create a project so we should use `new` argument.
72 |
73 | This argument will create a new project structure in current working directory. But we should give some project name to proceed. I will name the project as "my-first-app"
74 |
75 | ```
76 | ng new my-first-app
77 | ```
78 |
79 | After using this command in terminal some files will generated by `ng`. It will install necessary packages via npm. Wait until installation is done.
80 |
81 |
82 | ### Serving project
83 |
84 | We just create a new project. Proceed to `my-first-app` folder. Use `serve` command of `ng`. It will do packaging stuff and create a http server.
85 |
86 | ```
87 | cd my-first-app
88 | ng serve
89 | ```
90 |
91 | In terminal output, there should be a url address. If you can't figure the address then with `--port xxx` parameter, you can change port number to whatever you want.
92 |
93 | ```
94 | ng serve --port 8080
95 | ```
96 |
97 | Typescript compiled and Webpack packed your application.
98 |
99 | Now try to access to [http://localhost:8080](http://localhost:8080)
100 |
101 |
102 | ### Investigating created project
103 |
104 | > Before going deeper make sure you opened the project with an IDE software. I recommend Visual Studio Code or WebStorm..
105 |
106 | In project folder we can see `e2e` folder, `src` folder, and some files. `e2e` folder contains end to end testing stuff. We will check it after. All our project source stuff are in `src` folder. Other files contains information about configurations, required packages etc. We will check them when we need.
107 |
108 | Inside of `src` folder there are multiple files. The most important file in this folder is `index.html` file. This file is the highest point of our project. If you open it you will see something like this.
109 |
110 | ```html
111 |
112 |
113 |
114 |
115 | MyFirstApp
116 |
117 |
118 |
119 |
120 | Loading...
121 |
122 |
123 | ```
124 |
125 | In side of body element we have special tag which aren't in html standard. Its `app-root` element.
126 |
127 | If you check `app` folder. Go dive into `app.component.ts` file.
128 |
129 | ```ts
130 | import { Component } from '@angular/core';
131 |
132 | @Component({
133 | selector: 'app-root',
134 | templateUrl: './app.component.html',
135 | styleUrls: ['./app.component.css']
136 | })
137 | export class AppComponent {
138 | }
139 | ```
140 |
141 | As you can see there is some property `selector` is setted to `app-root`. In angular components will bind to element that given as `selector`. Selector is kinda like css element selector. If you use `name` then you will select `tag`, if you use `.name` then you will select `class`, if you use `[name]` you will select `property`.
142 |
143 | `templateUrl` property routes component's template location. You can use `template` property too if you don't want to create html file.
144 |
145 | ```ts
146 | import { Component } from '@angular/core';
147 |
148 | @Component({
149 | selector: 'app-root',
150 | template: `
151 | hi
152 | `,
153 | styleUrls: ['./app.component.css']
154 | })
155 | export class AppComponent {
156 | }
157 | ```
158 |
159 | `styleUrls` property shows us component's css file location. You can use `styles` too if you don't want to create css file. Difference between `template` and `styles`, styles is expecting an array of string, not directly string.
160 |
161 | ```ts
162 | import { Component } from '@angular/core';
163 |
164 | @Component({
165 | selector: 'app-root',
166 | template: `
167 | hi
168 | `,
169 | styles: [
170 | `b {
171 | color: red;
172 | }`
173 | ]
174 | })
175 | export class AppComponent {
176 | }
177 | ```
178 |
179 | `app.component.spec.ts` file contains information about tests. We will ignore it just for now.
180 |
181 | In angular projects works under modules. These modules look like `java packages` or `c# namespaces`. Your components defined in a module. `app.module.ts` file contains our main module.
182 |
183 | ```ts
184 | import { BrowserModule } from '@angular/platform-browser';
185 | import { NgModule } from '@angular/core';
186 | import { FormsModule } from '@angular/forms';
187 | import { HttpModule } from '@angular/http';
188 |
189 | import { AppComponent } from './app.component';
190 |
191 | @NgModule({
192 | declarations: [
193 | AppComponent
194 | ],
195 | imports: [
196 | BrowserModule,
197 | FormsModule,
198 | HttpModule
199 | ],
200 | providers: [],
201 | bootstrap: [AppComponent]
202 | })
203 | export class AppModule { }
204 | ```
205 |
206 | All components that using in this project should declared in this file. If we don't declare it, angular couldn't find component that we want to use.
207 |
208 | Rightnow I won't explain other files that we didn't check. We will come to them too.
209 |
210 | > Before going deeper I recommend to learn typescript. If you don't have a clue about it please check it.
211 |
212 |
213 | ### Creating a new component
214 |
215 | To create new component; first create a folder inside of `./src/app/` folder. We name it `server`.
216 |
217 | Inside of this folder create a file that called `server.component.ts`. Also you may create `server.component.html` too.
218 |
219 | In server.component.ts;
220 |
221 | ```ts
222 | export class ServerComponent {
223 |
224 | }
225 | ```
226 |
227 | We created a class that named `ServerComponent`. This class should exported out. We can't use if we didn't export it. we still have to do some stuff. We have to create a `decorator` that decorates this class is a `Component`. So lets do it?
228 |
229 | ```ts
230 | @Component({
231 |
232 | })
233 | export class ServerComponent {
234 |
235 | }
236 | ```
237 |
238 | But it won't compile. We have to import something.. `Component` decorator is defined in `@angular/core` package. We can import it from this package by like this.
239 |
240 | ```ts
241 | import { Component } from '@angular/core';
242 |
243 | @Component({
244 |
245 | })
246 | export class ServerComponent {
247 |
248 | }
249 | ```
250 |
251 | Now we created a component that angular could use. But still it is invalid. Because it's like untitled subject. It just there but no one could call it. So we have to declare some `selector`.
252 |
253 | ```ts
254 | import { Component } from '@angular/core';
255 |
256 | @Component({
257 | selector: 'app-server'
258 | })
259 | export class ServerComponent {
260 |
261 | }
262 | ```
263 |
264 | `selector` is similiar to css selector. If you just put something in there like this `app-server`; it would look for ``. If you put there `.app-server` then you get ``. You can even use `[app-server]` to look for properties. (like ``).
265 |
266 |
267 | We have to bind component's html file to component itself. We can use `templateUrl`. It is same as `app.component`.
268 |
269 | ```ts
270 | import {Component} from '@angular/core';
271 |
272 | @Component({
273 | selector: 'app-server',
274 | templateUrl: './server.component.html'
275 | })
276 | export class ServerComponent {
277 |
278 | }
279 | ```
280 |
281 | To use this component we have to add it to `app.module.ts`.
282 |
283 |
284 | ```ts
285 | import { BrowserModule } from '@angular/platform-browser';
286 | import { NgModule } from '@angular/core';
287 | import { FormsModule } from '@angular/forms';
288 | import { HttpModule } from '@angular/http';
289 |
290 | import { AppComponent } from './app.component';
291 | import { ServerComponent } from './server/server.component' // <<-- import first
292 |
293 | @NgModule({
294 | declarations: [
295 | AppComponent,
296 | ServerComponent // <<-- we have to add component here
297 | ],
298 | imports: [
299 | BrowserModule,
300 | FormsModule,
301 | HttpModule
302 | ],
303 | providers: [],
304 | bootstrap: [AppComponent]
305 | })
306 | export class AppModule { }
307 |
308 | ```
309 |
310 | I will change `server.component.html`
311 |
312 | ```html
313 | server component
314 | ```
315 |
316 | Now we can use this component. Create a new element in `app.component.html`.
317 |
318 | ```html
319 | app component
320 |
321 |
322 | ```
323 |
324 | Check out [http://localhost:8080](http://localhost:8080) now.
325 |
326 | 
327 |
328 | ### Create component with cli
329 |
330 | Sometimes we don't want to create basic structures over and over again. So `@angular/cli` has a solution. Using generate function of `ng` we can create components without any labor.
331 |
332 | ```
333 | ng generate component
334 | or
335 | ng g c
336 | ```
337 |
338 | for example, If we want to create servers component;
339 |
340 | ```
341 | ng generate component servers
342 | ```
343 |
344 | Will generate `servers` folder in `app` folder and It will create `ts`, `html`, `css` and `.spec.ts` files automaticly. Also it will add declaration to `app.module.ts`. Basically it makes component ready to use.
345 |
346 |
347 |
348 | ### Including bootstrap css to project
349 |
350 | We may need bootstrap for our project. How we import it? First we have to download the package.
351 |
352 | ```
353 | npm install bootstrap --save
354 | ```
355 |
356 | Then open the `.angular-cli.json` file. Modify it like this;
357 |
358 | ```js
359 | {
360 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
361 | "project": {
362 | "version": "1.0.0-beta.32.3",
363 | "name": "new-cli"
364 | },
365 | "apps": [
366 | {
367 | "root": "src",
368 | "outDir": "dist",
369 | "assets": [
370 | "assets",
371 | "favicon.ico"
372 | ],
373 | "index": "index.html",
374 | "main": "main.ts",
375 | "polyfills": "polyfills.ts",
376 | "test": "test.ts",
377 | "tsconfig": "tsconfig.json",
378 | "prefix": "app",
379 | "styles": [
380 | "../node_modules/bootstrap/dist/css/bootstrap.min.css", // <<-- we add this line
381 | "styles.css"
382 | ],
383 | "scripts": [],
384 | "environmentSource": "environments/environment.ts",
385 | "environments": {
386 | "dev": "environments/environment.ts",
387 | "prod": "environments/environment.prod.ts"
388 | }
389 | }
390 | ],
391 | "e2e": {
392 | "protractor": {
393 | "config": "./protractor.conf.js"
394 | }
395 | },
396 | "lint": [
397 | {
398 | "files": "src/**/*.ts",
399 | "project": "src/tsconfig.json"
400 | },
401 | {
402 | "files": "e2e/**/*.ts",
403 | "project": "e2e/tsconfig.json"
404 | }
405 | ],
406 | "test": {
407 | "karma": {
408 | "config": "./karma.conf.js"
409 | }
410 | },
411 | "defaults": {
412 | "styleExt": "css",
413 | "component": {}
414 | }
415 | }
416 |
417 | ```
418 |
419 | Now you can use bootstrap.
420 |
421 | >**Note:** There is a library for [bootstrap](https://github.com/ng-bootstrap/ng-bootstrap). It basically provides components too.
422 |
423 |
424 | ### Databinding
425 |
426 | Databinding is basically binding datas between template and class.
427 |
428 | * **OUT** String Interpolation: Bind a variable to template. Syntax `{{ data }}`
429 | * **OUT** Property Binding: Bind a variable to template's property. Syntax `[property]="data"`
430 | * **IN** Event Binding: Bind a event to class. Syntax `(event)="expression"`
431 |
432 | #### String Interpolation
433 |
434 | Lets a create basic component that writes a name. Name should provided with String Interpolation from a variable that we define in class.
435 |
436 | ```ts
437 | import { Component } from '@angular/core';
438 |
439 | @Component({
440 | selector: 'app-name',
441 | template: `
442 |
My name is {{name}}
443 | `
444 | })
445 | export class NameComponent {
446 | name: string = "Doğan";
447 | }
448 | ```
449 |
450 | Output:
451 |
452 | 
453 |
454 |
455 | This time lets add a 1 second timeout. After 1 second we will change the name to "Göksel"
456 |
457 | ```ts
458 | import { Component } from '@angular/core';
459 |
460 | @Component({
461 | selector: 'app-name',
462 | template: `
463 |
My name is {{name}}
464 | `
465 | })
466 | export class NameComponent {
467 | name: string = "Doğan";
468 |
469 | constructor() {
470 | setTimeout(() => {
471 | this.name = "Göksel";
472 | }, 1000);
473 | }
474 | }
475 | ```
476 |
477 | In the beginning it will show you ` My name is Doğan ` but after 1 second you will get ` My name is Göksel `. Databinding makes template render again. So you don't care rendering mechanism.
478 |
479 | #### Property binding and Event Binding
480 |
481 | This time we will use other binding types too.
482 |
483 | ```ts
484 | import { Component } from '@angular/core';
485 |
486 | @Component({
487 | selector: 'app-name',
488 | template: `
489 |
490 |
491 | `
492 | })
493 | export class NameComponent {
494 | isDisabled = true;
495 |
496 | someAction() {
497 | alert("hello");
498 | }
499 |
500 | changeDisabled() {
501 | this.isDisabled = !this.isDisabled; // reverse the value
502 | }
503 | }
504 | ```
505 |
506 | At the beginning regular button isn't clickable. But when we click second button it will be enabled and you get alert "hello" when you click it.
507 |
508 | #### Two way databinding
509 |
510 | There is one more databinding type of angular. Its called `Two way databinding`. This time events, properties and classes binded.
511 |
512 |
513 | ```ts
514 | import { Component } from '@angular/core';
515 |
516 | @Component({
517 | selector: 'app-name',
518 | template: `
519 |
520 |
521 |
My name is {{name}}
522 | `
523 | })
524 | export class NameComponent {
525 | name: string = "Doğan";
526 | }
527 | ```
528 |
529 | You will see that when input change class's name will automaticly change and then `My name is ____` will automaticly render back. If you change name from class then input's value will change too.
530 |
531 | > **Note:** `ngModel` should be imported in `app.module.ts` file. Required module is `FormsModule`.
532 |
533 | ### Directives
534 |
535 | There are 3 kinds of directives.
536 |
537 | * Components
538 | * Structural Directives (you will see this as star `*` character)
539 | * Attribute Directives
540 |
541 | You already know the components. Lets dive into structural directives.
542 |
543 | These directives are control full of dom. You may ask why?
544 |
545 | #### ngIf
546 |
547 | Lets check an example of `*ngIf`
548 |
549 |
550 | ```ts
551 | import { Component } from '@angular/core';
552 |
553 | @Component({
554 | selector: 'app-name',
555 | template: `
556 |
557 |
558 | I'm visible now
559 |
560 | `
561 | })
562 | export class NameComponent {
563 | visible: boolean = false;
564 | }
565 | ```
566 |
567 | In this example when you click the button, some text appears. But interesting part is when visible is false, p element won't exist. It will be created when visible is true. Structural directives modify current dom and remove.
568 |
569 | You can use else syntax (Angular 4) too.
570 |
571 |
572 | ```ts
573 | import { Component } from '@angular/core';
574 |
575 | @Component({
576 | selector: 'app-name',
577 | template: `
578 |
579 |
580 | I'm visible now
581 |
582 |
583 |
584 | I'm hidden
585 |
586 |
587 |
588 | `
589 | })
590 | export class NameComponent {
591 | visible: boolean = false;
592 | }
593 | ```
594 |
595 | Please try it before continue.
596 |
597 | #### ngFor
598 |
599 | ngFor is a structural directive too. It will modify and clone itself as given array. For example;
600 |
601 | ```ts
602 | import { Component } from '@angular/core';
603 |
604 | @Component({
605 | selector: 'app-name',
606 | template: `
607 |
608 |
{{car}}
609 |
610 | `
611 | })
612 | export class NameComponent {
613 | cars = [
614 | 'Toyota',
615 | 'Honda',
616 | 'Ford'
617 | ]
618 | }
619 | ```
620 |
621 | 
622 |
623 | ngFor also has a index syntax. If you use a `;` character then define a variable that equals the index; you can use the index in the scope.
624 |
625 | ```ts
626 | import { Component } from '@angular/core';
627 |
628 | @Component({
629 | selector: 'app-name',
630 | template: `
631 |
661 | `
662 | })
663 | export class NameComponent {
664 | cars = [
665 | {
666 | name: 'Toyota',
667 | total: 1
668 | },
669 | {
670 | name: 'Ford',
671 | total: 0
672 | }
673 | ]
674 | }
675 | ```
676 |
677 | You will see that Toyota item will green but Ford item will red.
678 |
679 | #### ngClass
680 |
681 | ngClass is an attribute directive too.
682 |
683 | ```ts
684 | import { Component } from '@angular/core';
685 |
686 | @Component({
687 | selector: 'app-name',
688 | template: `
689 |
690 |
{{car.name}}
691 |
692 | `,
693 |
694 | styles: [
695 | `.notInStock {
696 | background-color: red
697 | }`
698 | ]
699 | })
700 | export class NameComponent {
701 | cars = [
702 | {
703 | name: 'Toyota',
704 | total: 1
705 | },
706 | {
707 | name: 'Ford',
708 | total: 0
709 | },
710 | ]
711 | }
712 | ```
713 |
714 | You will see that Toyota item will looking normal but Ford item will be red.
715 |
716 | #### ngSwitch
717 |
718 | ngSwitch is for switching between multiple cases. Its very usefull built-in directive.
719 |
720 | ```ts
721 | import { Component } from '@angular/core';
722 |
723 | @Component({
724 | selector: 'app-name',
725 | template: `
726 |
727 |
Count is 5
728 |
Count is 10
729 |
Count is Default
730 |
731 | `
732 | })
733 | export class NameComponent {
734 | count: number = 5;
735 | }
736 | ```
737 |
738 |
739 | ### Input
740 |
741 | In this chapter our goal is making some property to accessible from outside. You may ask why we need this? We creating components that has own scope. For example we create "create new user" component and "user list" component. So one component must effect to another one.
742 |
743 | First lets do what we wanted. We will create some components.
744 |
745 | ```bash
746 | ng new my-second-app
747 | cd my-second-app
748 | ng g c users --spec false #-- spec false blocks spec file generation
749 | ng g c users/user-list --spec false # users/list syntax will create a component in users folder.
750 | ng g c users/user-item --spec false
751 | ng g c users/user-create --spec false
752 | ```
753 |
754 | Edit app.component.html as this
755 |
756 | ```html
757 |
758 | ```
759 |
760 |
761 | Edit users.component.html as this
762 |
763 | ```html
764 |
765 |
766 |
767 | ```
768 |
769 | Add an array to user-list component file.
770 |
771 | ```ts
772 | import { Component, OnInit } from '@angular/core';
773 |
774 | @Component({
775 | selector: 'app-user-list',
776 | templateUrl: './user-list.component.html',
777 | styleUrls: ['./user-list.component.css']
778 | })
779 | export class UserListComponent implements OnInit {
780 | users = ['Jack', 'George', 'Another common name']; // << this line
781 |
782 | constructor() { }
783 |
784 | ngOnInit() {
785 | }
786 | }
787 | ```
788 |
789 | Edit user-list.component.html as this
790 |
791 | ```html
792 |
793 | ```
794 |
795 | Edit user-item.component.html and user-item.component.ts as like this.
796 |
797 | ```html
798 |
799 | User name: {{name}}
800 |
801 |
802 |
803 | ```
804 |
805 | ```ts
806 | import { Component, OnInit } from '@angular/core';
807 |
808 | @Component({
809 | selector: 'app-user-item',
810 | templateUrl: './user-item.component.html',
811 | styleUrls: ['./user-item.component.css']
812 | })
813 | export class UserItemComponent implements OnInit {
814 | name: string;
815 | constructor() { }
816 |
817 | ngOnInit() {
818 | }
819 |
820 | }
821 | ```
822 |
823 | So now we ready to process. If you get this point you probably see this screen.
824 |
825 | 
826 |
827 | User fields are created but name seems doesn't work at all. We have to do something don't we. UserItemComponent element's name property cannot be accessed by other component because it works in own closure. We have to add a decorator to access. Its called `@Input`
828 |
829 | We now editing user.component.ts
830 |
831 |
832 | ```ts
833 | import { Component, OnInit } from '@angular/core';
834 |
835 | @Component({
836 | selector: 'app-user-item',
837 | templateUrl: './user-item.component.html',
838 | styleUrls: ['./user-item.component.css']
839 | })
840 | export class UserItemComponent implements OnInit {
841 | @Input() name: string;
842 | constructor() { }
843 |
844 | ngOnInit() {
845 | }
846 |
847 | }
848 | ```
849 |
850 | `@Input` decorator is actually decorator generating function. So we have to call it like `@Input()`. You can use the first parameter as alias. I will give you an example for it too.
851 |
852 | Now we test our application but result is same. Nothing changed :worried:
853 |
854 | 
855 |
856 | We forgot to set name because we never set it or access it from outside of user-item component.
857 |
858 | Edit the user-list.component.html
859 |
860 | ```html
861 |
862 | ```
863 |
864 | As you can see, we used a property binding. Basically `@Input` working as property. We set the value as user, because we declared a variable as `user` in ngFor directive.
865 |
866 | Now give a shot.
867 |
868 | 
869 |
870 | Lets check example of the alias parameter `@Input()`.
871 |
872 | app-user-item.ts
873 |
874 | ```ts
875 | import { Component, OnInit } from '@angular/core';
876 |
877 | @Component({
878 | selector: 'app-user-item',
879 | templateUrl: './user-item.component.html',
880 | styleUrls: ['./user-item.component.css']
881 | })
882 | export class UserItemComponent implements OnInit {
883 | @Input('user') name: string; // << as you can see we give some parameter
884 | constructor() { }
885 |
886 | ngOnInit() {
887 | }
888 |
889 | }
890 | ```
891 |
892 | Now component looking for `user` property.
893 |
894 |
895 | Edit the user-list.component.html
896 |
897 | ```html
898 |
899 | ```
900 |
901 | ### Output
902 |
903 | Last chapter we dive into Input. In our example we created edit and delete buttons. Also we must have a working user-create component too. Lets check it.
904 |
905 | user-create.component.html
906 |
907 | ```html
908 | name:
909 |
910 | ```
911 |
912 | user-create.component.ts
913 |
914 | ```ts
915 | import { Component, OnInit, Output, EventEmitter } from '@angular/core';
916 |
917 | @Component({
918 | selector: 'app-user-create',
919 | templateUrl: './user-create.component.html',
920 | styleUrls: ['./user-create.component.css']
921 | })
922 | export class UserCreateComponent implements OnInit {
923 |
924 | constructor() { }
925 |
926 | ngOnInit() {
927 | }
928 |
929 | name: string; // two-way-binding property
930 |
931 | @Output()
932 | onUserCreated = new EventEmitter(); // this is the our event that can be binded out of this component
933 | // note: EventEmitter should be imported from @angular/core
934 |
935 | onUserCreate() { // this function get trigger when user click button
936 | this.onUserCreated.emit(this.name); // we send data to eventemitter
937 | }
938 | }
939 | ```
940 |
941 | > **Note:** I will move users to upper component.
942 |
943 | users.component.html
944 |
945 | ```html
946 |
947 |
948 |
949 | ```
950 |
951 | users.component.ts
952 |
953 | ```ts
954 | import { Component, OnInit } from '@angular/core';
955 |
956 | @Component({
957 | selector: 'app-users',
958 | templateUrl: './users.component.html',
959 | styleUrls: ['./users.component.css']
960 | })
961 | export class UsersComponent implements OnInit {
962 | users = ['Jack', 'George', 'Another common name'];
963 |
964 | constructor() { }
965 |
966 | ngOnInit() {
967 | }
968 |
969 | onUserCreated(name) {
970 | this.users.push(name);
971 | }
972 | }
973 | ```
974 |
975 | user-list.component.ts
976 |
977 | ```ts
978 | import { Component, OnInit, Input } from '@angular/core';
979 |
980 | @Component({
981 | selector: 'app-user-list',
982 | templateUrl: './user-list.component.html',
983 | styleUrls: ['./user-list.component.css']
984 | })
985 | export class UserListComponent implements OnInit {
986 | @Input() // added this
987 | users;
988 |
989 | constructor() { }
990 |
991 | ngOnInit() {
992 | }
993 |
994 | }
995 | ```
996 |
997 | Lets check our application. We type some name to input. Then click the create button. :sunglasses:
998 |
999 | ### View Encapsulation
1000 |
1001 | Component's css files are specific to component. For example in css file;
1002 |
1003 | ```css
1004 | b {
1005 | color: red;
1006 | }
1007 | ```
1008 |
1009 | This css compiled with some property selector so this way other components b element won't get any effect but you may don't want to do that. Simply changing encapsulation can modify this feature.
1010 |
1011 | ```ts
1012 | import { Component, ViewEncapsulation } from '@angular/core';
1013 |
1014 | @Component({
1015 | selector: 'app-some',
1016 | templateUrl: './some.component.html',
1017 | styleUrls: ['./some.component.css'],
1018 | encapsulation: ViewEncapsulation.None
1019 | })
1020 | export class SomeComponent {
1021 |
1022 | }
1023 | ```
1024 |
1025 | ### Local reference
1026 |
1027 | Local reference makes a marking for DOM elements. We use that in `*ngIf` structure directive section. There is one more thing that I should write and thats named `@ViewChild` decorator.
1028 |
1029 | This decorator allows to access DOM element from code. If you know what are you going to do then you can use this decorator, otherwise please avoid using this feature.
1030 |
1031 | ```ts
1032 | import { Component, ViewChild, ElementRef } from '@angular/core';
1033 |
1034 | @Component({
1035 | selector: 'app-some',
1036 | template: `
1037 |
1038 |
1039 |
1040 | `
1041 | })
1042 | export class SomeComponent {
1043 | @ViewChild('localReference')
1044 | localReferenceDiv: ElementRef;
1045 | }
1046 | ```
1047 |
1048 |
1049 | ### ng-content
1050 |
1051 | ng-content is a special directive that provide element's content. Normally angular will override the content of components. `Loading...` is good example for this consept. When angular handle `app-root` then `Loading` text will disapear. But what if we want to show it.
1052 |
1053 | Let me show you an example.
1054 |
1055 | ```ts
1056 | import { Component } from '@angular/core';
1057 |
1058 | @Component({
1059 | selector: 'app-bold',
1060 | template: `
1061 |
1062 |
1063 |
1064 | `
1065 | })
1066 | export class BoldComponent {
1067 | }
1068 | ```
1069 |
1070 | ```ts
1071 | import { Component } from '@angular/core';
1072 |
1073 | @Component({
1074 | selector: 'app-root',
1075 | template: `
1076 | this text will be bold
1077 | `
1078 | })
1079 | export class AppComponent {
1080 | }
1081 | ```
1082 |
1083 | > **Note:** Last chapter we learnt ViewChild. If you want to use ViewChild in a content it won't work. You have to use `@ContentChild`
1084 |
1085 | ### Life cycle of components
1086 |
1087 | Components have a standard life cycle. They all have these things. We can hook them.
1088 |
1089 | * ngOnChanges: Called after a bound input proerty changes
1090 | * ngOnInit: Called once the component initalized
1091 | * ngDoCheck: Called during every change detection run
1092 | * ngAfterContentInit: Called after content (ng-content) has been projected into view
1093 | * ngAfterContentChecked: Called every time the projected content has been checked
1094 | * ngAfterViewInit: Called after the component's view (and child views) has been initalized.
1095 | * ngAfterViewChecked: Called every time the view (and child views) has been checked.
1096 | * ngOnDestroy: Called once the components is about the be destroyed.
1097 |
1098 | ```ts
1099 | import { Component, OnInit, OnChanges, SimpleChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy } from '@angular/core';
1100 |
1101 | @Component({
1102 | selector: 'app-some',
1103 | template: ` `
1104 | })
1105 | export class SomeComponent implements OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy {
1106 |
1107 | ngOnChanges(changes: SimpleChanges): void {
1108 | console.log('ngOnChanges', changes);
1109 | }
1110 |
1111 | ngOnInit(): void {
1112 | console.log('ngOnInit');
1113 | }
1114 |
1115 | ngDoCheck(): void {
1116 | console.log('ngDoCheck');
1117 | }
1118 |
1119 | ngAfterContentInit(): void {
1120 | console.log('ngAfterContentInit');
1121 | }
1122 |
1123 | ngAfterContentChecked(): void {
1124 | console.log('ngAfterContentChecked');
1125 | }
1126 |
1127 | ngAfterViewChecked(): void {
1128 | console.log('ngAfterViewChecked');
1129 | }
1130 |
1131 | ngAfterViewInit(): void {
1132 | console.log('ngAfterViewInit');
1133 | }
1134 |
1135 | ngOnDestroy(): void {
1136 | console.log('ngOnDestroy');
1137 | }
1138 | }
1139 | ```
1140 |
1141 |
1142 | ### Creating a new directive
1143 |
1144 | We saw some already defined directives. But how we can defire new? This chapter we will dive into that.
1145 |
1146 | Directives are defining just like components. You have to add them to app.module.ts. We can create manual but I will use @angular/cli.
1147 |
1148 | ```
1149 | ng generate directive
1150 | or
1151 | ng g d
1152 | ```
1153 |
1154 | I will create a green directive that makes elements green on hover.
1155 |
1156 | ```
1157 | ng g d green
1158 | ```
1159 |
1160 | I remove spec.ts file because we don't care tests just now. There should be green.directive.ts file. Directive files are created as `.directive.ts` syntax.
1161 |
1162 | ```ts
1163 | import { Directive } from '@angular/core';
1164 |
1165 | @Directive({
1166 | selector: '[appGreen]'
1167 | })
1168 | export class GreenDirective {
1169 | constructor() { }
1170 | }
1171 | ```
1172 |
1173 | This directive will handle the `appGreen` property. If you use somewhere else this then directive will bound to element.
1174 |
1175 | #### HostListener
1176 |
1177 | We trying to make green element whenever mouse hover's the element so we have to catch the events.
1178 |
1179 | ```ts
1180 | import { Directive, HostListener } from '@angular/core';
1181 |
1182 | @Directive({
1183 | selector: '[appGreen]'
1184 | })
1185 | export class GreenDirective {
1186 | constructor() { }
1187 |
1188 | @HostListener('mouseenter')
1189 | mouseenter() {
1190 | // mouse enters
1191 | }
1192 |
1193 | @HostListener('mouseleave')
1194 | mouseleave() {
1195 | // mouse leaves
1196 | }
1197 | }
1198 | ```
1199 |
1200 | #### HostBinding
1201 |
1202 | How about to change colors? Now we use `@HostBinding`.
1203 |
1204 | ```ts
1205 | import { Directive, HostBinding, HostListener } from '@angular/core';
1206 |
1207 | @Directive({
1208 | selector: '[appGreen]'
1209 | })
1210 | export class GreenDirective {
1211 | @HostBinding('style.backgroundColor') backgroundColor: string = 'transparent';
1212 |
1213 | @HostListener('mouseenter')
1214 | mouseenter() {
1215 | this.backgroundColor = 'green';
1216 | }
1217 |
1218 | @HostListener('mouseleave')
1219 | mouseleave() {
1220 | this.backgroundColor = 'transparent';
1221 | }
1222 | }
1223 | ```
1224 |
1225 | ### Services and dependency injection
1226 |
1227 | Services useful to carry data between components. We do not require any decorator to create service. Lets create an user service.
1228 |
1229 | I recommend to create file as `.service.ts` syntax.
1230 |
1231 | So lets create a new users.service.ts file on `app` folder.
1232 |
1233 | ```ts
1234 | export class UserService {
1235 | users = [
1236 | {id: 1, name: 'co3moz'},
1237 | {id: 2, name: 'goxel'}
1238 | {id: 3, name: 'Ilrkhoaktul'}
1239 | ]
1240 |
1241 | getUsers() {
1242 | return this.users;
1243 | }
1244 |
1245 | addUser(user: {id: number, name: string}) {
1246 | this.users.push(user);
1247 | }
1248 |
1249 | removeUser(id: number) {
1250 | this.users.splice(id, 1);
1251 | }
1252 | }
1253 | ```
1254 |
1255 | We basically create an users service class with some property and functions.
1256 |
1257 | Lets use it from a component.
1258 |
1259 | ```ts
1260 | import { UserService } from 'user.service';
1261 | import { Component } from '@angular/core';
1262 |
1263 | @Component({
1264 | selector: 'app-user-list',
1265 | template: `
1266 |
{{ user.name }}
1267 | `,
1268 | providers: [
1269 | UserService
1270 | ]
1271 | })
1272 | export class UserListComponent implements OnInit {
1273 | users;
1274 | constructor(private userService: UserService) {} // userService's type must be declared. Otherwise it won't work.
1275 |
1276 | ngOnInit() {
1277 | this.users = this.userService.getUsers(); // pass reference of array to local variable.
1278 | }
1279 | }
1280 | ```
1281 |
1282 | > **Important Note:** Providers will provide a service to component but every creation of userlistComponent will make own UserService. Because we said to component when you initializing create a new service that called UserService. But what if we just want to application wide? We may need to use this datas from outside of this component. We have to use app.module.ts file for this job. Inside of app.module.ts there is providers section that we can put our service.
1283 |
1284 | > **Important Note 2:** Children of userListComponent can access same service if they didn't declared a new provider of UserService. So Providers section of component should be used only for creating new provider.
1285 |
1286 | You can use `@angular/cli` to generate service
1287 |
1288 | ```
1289 | ng generate service
1290 | or
1291 | ng g s
1292 | ```
1293 |
1294 | #### Injecting a service into another service
1295 |
1296 | We may need a service inside of another service. For example we may have a logging service and this service may required to other places. So how we use another service in our service?
1297 |
1298 | There you go, some example of `@Injectable`
1299 |
1300 | ```ts
1301 | import { LoggingService } from 'logging.service';
1302 | import { Injectable } from '@angular/core';
1303 |
1304 | @Injectable()
1305 | export class UserService {
1306 | users = [
1307 | {id: 1, name: 'co3moz'},
1308 | {id: 2, name: 'goxel'}
1309 | {id: 3, name: 'Ilrkhoaktul'}
1310 | ];
1311 |
1312 | constructor(private loggingService: LoggingService) {
1313 |
1314 | }
1315 |
1316 | getUsers() {
1317 | return this.users;
1318 | }
1319 |
1320 | addUser(user: {id: number, name: string}) {
1321 | this.users.push(user);
1322 | this.loggingService.log('user added');
1323 | }
1324 |
1325 | removeUser(id: number) {
1326 | this.users.splice(id, 1);
1327 | this.loggingService.log('user removed');
1328 | }
1329 | }
1330 | ```
1331 |
1332 |
1333 | #### Event emitting service
1334 |
1335 | We may need a event that emits some information.
1336 |
1337 | ```ts
1338 | import { LoggingService } from 'logging.service';
1339 | import { Injectable, EventEmitter } from '@angular/core';
1340 |
1341 | @Injectable()
1342 | export class UserService {
1343 | users = [
1344 | {id: 1, name: 'co3moz'},
1345 | {id: 2, name: 'goxel'}
1346 | {id: 3, name: 'Ilrkhoaktul'}
1347 | ];
1348 |
1349 | constructor(private loggingService: LoggingService) {
1350 |
1351 | }
1352 |
1353 | userCreated = new EventEmitter<{id: number, name: string}>();
1354 |
1355 | getUsers() {
1356 | return this.users;
1357 | }
1358 |
1359 | addUser(user: {id: number, name: string}) {
1360 | this.users.push(user);
1361 | this.userCreated.emit(user);
1362 | this.loggingService.log('user added');
1363 | }
1364 |
1365 | removeUser(id: number) {
1366 | this.users.splice(id, 1);
1367 | this.loggingService.log('user removed');
1368 | }
1369 | }
1370 | ```
1371 |
1372 | In component we can just subscribe the event. We will learn better feature so this feature is just for knowledge.
1373 |
1374 | ```ts
1375 | import { UserService } from 'user.service';
1376 | import { Component } from '@angular/core';
1377 |
1378 | @Component({
1379 | selector: 'app-user-list',
1380 | template: `
1381 |
{{ user.name }}
1382 | `,
1383 | providers: [
1384 | UserService
1385 | ]
1386 | })
1387 | export class UserListComponent implements OnInit {
1388 | users;
1389 | constructor(private userService: UserService) {
1390 | this.userService.userCreated.subscribe((user) => {
1391 | console.log('new user just created');
1392 | });
1393 | } // userService's type must be declared. Otherwise it won't work.
1394 |
1395 | ngOnInit() {
1396 | this.users = this.userService.getUsers(); // pass reference of array to local variable.
1397 | }
1398 | }
1399 | ```
1400 |
1401 | > **Important Note:** When you subscribing manually don't forget to unsubscribe with `ngOnDestroy`.
1402 |
1403 |
1404 | ### Router
1405 |
1406 | Router is routes components as pages. To you router first go `app.module.ts`
1407 |
1408 | Import the Routes from `@angular/router`
1409 |
1410 | ```ts
1411 | import { Routes, RouterModule } from '@angular/router';
1412 | ```
1413 |
1414 | Then create a array that contains following objects.
1415 |
1416 | ```ts
1417 | const appRoutes: Routes = [
1418 | { path: 'users', component: UsersComponent}
1419 | ];
1420 | ```
1421 |
1422 | `path` declares a route in browser. for example `users` makes routes for `/users`. If path given as empty string then it routes for ` ` so this means we can make a home page.
1423 |
1424 | ```ts
1425 | const appRoutes: Routes = [
1426 | { path: '', component: HomeComponent},
1427 | { path: 'users', component: UsersComponent}
1428 | ];
1429 | ```
1430 |
1431 | Also you must add `RouterModule.forRoot(appRoutes)` to imports section of `AppModule`.
1432 |
1433 | > **Note** You may create a `app.route.ts` or `app.routing.ts` file. Its your decision.
1434 |
1435 | Now we have to declare where will content go? we will use ``.
1436 |
1437 | I will add this to app.component.html.
1438 |
1439 | #### Links
1440 |
1441 | In this sub-chapter we will learn router links.
1442 |
1443 | Normally to make link we simple use `href`.
1444 |
1445 | ```html
1446 | Home
1447 | ```
1448 |
1449 | But for angular its invalid because every click causes full page reload. Our application must be stable as possible as can.
1450 |
1451 | We will use `routerLink` directive.
1452 |
1453 | ```html
1454 | Home
1455 | ```
1456 |
1457 | You may use `[]` syntax for expressions.
1458 |
1459 | ```html
1460 | Home
1461 | ```
1462 |
1463 | #### Active route
1464 |
1465 | We may need to style active page or etc. To archive this we will use `routerLinkActive`.
1466 |
1467 | ```html
1468 |
1471 | ```
1472 |
1473 | routerLinkActive directive has a another directive that named `routerLinkActiveOptions`. With routerLinkActiveOptions we can give options to routerLinkActive. For example for full path check;
1474 |
1475 | ```html
1476 |
1479 | ```
1480 |
1481 | #### Navigating from code
1482 |
1483 | Accesing the router from a component might be useful sometimes.
1484 |
1485 | ```ts
1486 | import { Component } from '@angular/core';
1487 | import { Router } from '@angular/router';
1488 |
1489 | @Component({
1490 | selector: 'app-user-list',
1491 | template: ``
1492 | })
1493 | export class UserListComponent {
1494 | constructor(private router: Router) {
1495 | }
1496 |
1497 | navigateSomewhereElse() {
1498 | this.router.navigate(['/home']);
1499 | }
1500 |
1501 | }
1502 | ```
1503 |
1504 |
1505 | #### Parameters of routes
1506 |
1507 | Examples can show everything.
1508 |
1509 | ```ts
1510 | const appRoutes: Routes = [
1511 | { path: '', component: HomeComponent},
1512 | { path: 'users/:id', component: UsersComponent}
1513 | ];
1514 | ```
1515 |
1516 | ```ts
1517 | import { Component } from '@angular/core';
1518 | import { ActivatedRoute } from '@angular/router';
1519 |
1520 | @Component({
1521 | selector: 'app-user-list',
1522 | template: ``
1523 | })
1524 | export class UsersComponent {
1525 | constructor(private route: ActivatedRoute) {
1526 | }
1527 |
1528 | getIdParameter() {
1529 | return this.route.snapshot.params['id'];
1530 | }
1531 |
1532 | }
1533 | ```
1534 |
1535 | #### Nested routes
1536 |
1537 | Nested routes are useful when we need show multiple components at same time.
1538 |
1539 | ```ts
1540 | const appRoutes: Routes = [
1541 | { path: '', component: HomeComponent },
1542 | { path: 'users', component: UsersComponent, children: [
1543 | { path: ':id', component: UserComponent },
1544 | { path: ':id/edit', component: UserEditComponent }
1545 | ]}
1546 | ];
1547 | ```
1548 |
1549 | Don't forget to add `` to parent component.
1550 |
1551 |
1552 | #### Redirecting
1553 |
1554 | We may need a redirecting route. I achive that we simple add a route which doesn't have component property. It needs only `redirectTo` parameter.
1555 |
1556 | ```ts
1557 | const appRoutes: Routes = [
1558 | { path: '', component: HomeComponent },
1559 | { path: 'users', component: UsersComponent },
1560 | { path: 'people', redirectTo: '/users' }
1561 | ];
1562 | ```
1563 |
1564 | With this feature and wildcard feature we can make 404 pages.
1565 |
1566 |
1567 | ```ts
1568 | const appRoutes: Routes = [
1569 | { path: '', component: HomeComponent },
1570 | { path: 'users', component: UsersComponent },
1571 | { path: 'not-found', component: NotFoundComponent },
1572 | { path: '**', redirectTo: '/not-found' } // make sure wildcard is at the end.
1573 | ];
1574 | ```
1575 |
1576 | Simply other routes will redirected to `NotFoundComponent`
1577 |
--------------------------------------------------------------------------------
/images/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/co3moz/angular4-notes/f55a058a68d7cb2c8be399bd7a08aa961e38f66e/images/1.png
--------------------------------------------------------------------------------
/images/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/co3moz/angular4-notes/f55a058a68d7cb2c8be399bd7a08aa961e38f66e/images/2.png
--------------------------------------------------------------------------------
/images/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/co3moz/angular4-notes/f55a058a68d7cb2c8be399bd7a08aa961e38f66e/images/3.png
--------------------------------------------------------------------------------
/images/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/co3moz/angular4-notes/f55a058a68d7cb2c8be399bd7a08aa961e38f66e/images/4.png
--------------------------------------------------------------------------------
/images/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/co3moz/angular4-notes/f55a058a68d7cb2c8be399bd7a08aa961e38f66e/images/5.png
--------------------------------------------------------------------------------
/images/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/co3moz/angular4-notes/f55a058a68d7cb2c8be399bd7a08aa961e38f66e/images/6.png
--------------------------------------------------------------------------------
/lang/README.tr.md:
--------------------------------------------------------------------------------
1 | Angular 4 - Notları
2 | ====================
3 |
4 | Bu kod deposu benim angular 4 notlarımın bir derlemesidir. Angular 2'yi deneyememiştim. Fakat şimdi Angular 4'e bir göz atmaya ve bir ders hazırlamaya karar verdim. Öğrendiğim her şeyi yazacağım, belki bu kod deposu sizin için de rehber olabilir.
5 |
6 | [Maximilian Schwarzmuller](https://www.udemy.com/the-complete-guide-to-angular-2)'e bu harika rehber için teşekkürler.
7 |
8 | > **Yazar notu:** Türkçe çeviriyi üşenmeden yaptığı için [Furkan Başaran](http://github.com/frknbasaran) 'a teşekkürler.
9 |
10 | İçindekiler
11 | ----------------
12 |
13 | - [Kurulum](#installation)
14 | - [Bir proje yaratmak](#creating-project)
15 | - [Projeyi çalıştırmak](#serving-project)
16 | - [Çalıştırılmış Projeyi İncelemek](#investigating-created-project)
17 | - [Yeni bir komponent oluşturmak](#creating-a-new-component)
18 | - [Komut satırı ile bir komponent oluşturmak](#create-component-with-cli)
19 | - [Projeye bootstrap css eklemek](#including-bootstrap-css-to-project)
20 | - [Databinding](#databinding)
21 | - [Direktifler](#directives)
22 | - [ngIf](#ngif)
23 | - [ngFor](#ngfor)
24 | - [ngStyle](#ngstyle)
25 | - [ngClass](#ngclass)
26 | - [ngSwitch](#ngswitch)
27 | - [Input](#input)
28 | - [Output](#output)
29 | - [View Encapsulation](#view-encapsulation)
30 | - [Yerel Referanslar](#local-reference)
31 | - [ng-content](#ng-content)
32 | - [Komponentlerin Yaşam Döngüsü](#life-cycle-of-components)
33 | - [Yeni bir direktif oluşturmak](#creating-a-new-directive)
34 | - [HostListener](#hostlistener)
35 | - [HostBinding](#hostbinding)
36 | - [Servisler ve Bağlılıkların Zerki](#services-and-dependency-injection)
37 | - [Bir servisi bir başka servise zerk etmek](#injecting-a-service-into-another-service)
38 | - [Olay yayınlama servisi](#event-emitting-service)
39 | - [Router](#router)
40 | - [Links](#links)
41 | - [Active Router](#active-route)
42 | - [Kod içinden yönlendirme](#navigating-from-code)
43 | - [Route Parameters](#parameters-of-routes)
44 | - [Nested Routes](#nested-routes)
45 | - [Yönlendirme](#redirecting)
46 |
47 | ### Kurulum
48 |
49 | Uygulama geliştirmek için ilk önce node.js kurmamız gerekiyor. Eğer node.js nedir bilmiyorsanız Angular 4'ten önce lütfen ona bir göz atın. Biz angular komut satırı eklentisini kullanacağız, bu eklenti bize projelerimizi yaratırken yardımcı olacak. Oldukça kullanışlı bir araç.
50 |
51 | ```
52 | npm i @angular/cli -g
53 | ```
54 |
55 | Angular komut satırı paketini `@angular/cli` global parametresiyle yüklemeliyiz. Bu parametre proje lokaline değil global node_modules klasörüne kurulum sağlayacaktır.
56 |
57 | Artık terminalde `ng` komutunu kullanabiliyor olmamız gerek.
58 |
59 | ### Proje yaratmak
60 |
61 | Proje yaratmak için `ng` komutunu kullanacağız. Eğer terminale `ng` yazdığınızda bir hata alıyorsanız `Kurulum` adımında bir hata yapmışsınız demektir, lütfen o adıma gidip işlemleri doğru şekilde tamamladığınızdan emin olun.
62 |
63 | `ng` komutu birden fazla opsiyonel parametreye sahiptir. O konuya da geleceğiz ancak öncelikle bir proje yaratmak için `new` parametresini kullanmalıyız.
64 |
65 | Bu parametre güncel dizinimizde yeni bir proje yapısı oluşturacaktır. Ancak işlem sırasında bir proje ismi vermeliyiz. Ben proje ismi olarak ilk uygulamam anlamına gelen "my-first-app" ismini seçtim.
66 |
67 | ```
68 | ng new my-first-app
69 | ```
70 |
71 | Bu komutu kullandıktan sonra terminalimiz `ng` tarafından bazı dosyalar oluşturacak. Ardından gerekli npm paketlerini yükleyecek, işlemler tamamlanana kadar bekleyin.
72 |
73 | ### Projeyi çalıştırmak
74 |
75 | Az önce yeni bir proje oluşturduk. `my-first-app` klasörüne girip `ng` nin `serve` komutunu kullanırsak yüklenen paketler bir http sunucusu oluşturup yayına başlayacaktır.
76 |
77 | ```
78 | cd my-first-app
79 | ng serve
80 | ```
81 |
82 | Terminal çıktımızda bir url adresi olmalı. İsterseniz seçiminize bağlı olarak `--port xx` parametresiyle uygulamanın istediğiniz herhangi bir porttan yayınlanmasını sağlayabilirsiniz.
83 |
84 | ```
85 | ng serve --port 8080
86 | ```
87 |
88 | Typescript javascript'e çevrildi ve Webpack uygulamanızı paketledi.
89 | Artık localhost:8080 adresnden uygulamaya erişebilirsiniz.
90 |
91 |
92 | ### Çalıştırılmış Projeyi İncelemek
93 |
94 | > Daha fazla derinlere inmeden önce projeyi bir IDE ile açtığınızdan emin olun. Ben Visual Studio Code ya da WebStorm tavsiye ediyorum.
95 |
96 | Proje dizininde `e2e` klasörünü, `src` klasörünü ve birkaç dosyayı göreceğiz. `e2e` klasörünü uçtan uca testleri içerir. Buna daha sonra göz atacağız. (Testlerin kaderi bu.) Projemizin tüm kaynak dosyaları `src` klasöründe bulunur. Diğer dosyalar da proje konfigürasyonlarıyla ilgili bilgileri, paket bağımlılıklarını ve benzeri detayları içerirler. İhtiyaç duyduğumuzda onlarla tekrar ilgileneceğiz.
97 |
98 | `src` klasörünün içinde birden fazla dosya var. Bu dizindeki en önemli dosya `index.html` dosyası. Bu dosya projemizin en üst noktası. Eğer dosyayı açarsanız aşağıdaki gibi olduğunu göreceksiniz.
99 |
100 |
101 | ```html
102 |
103 |
104 |
105 |
106 | MyFirstApp
107 |
108 |
109 |
110 |
111 | Loading...
112 |
113 |
114 | ```
115 |
116 | Body etiketinin içinde html standardına uymayan özel bir etiketimiz var, `app-root` elementi.
117 |
118 | Eğer `app` klasörüne göz atarsanız ve `app.component.ts` adlı dosyayı açarsanız aşağıdaki gibi olduğunu göreceksiniz.
119 |
120 | ```ts
121 | import { Component } from '@angular/core';
122 |
123 | @Component({
124 | selector: 'app-root',
125 | templateUrl: './app.component.html',
126 | styleUrls: ['./app.component.css']
127 | })
128 | export class AppComponent {
129 | }
130 | ```
131 |
132 | Gördüğünüz gibi 'selector' olarak 'app-root' seçilmiş. Angular komponentleri elementlere `selector` adı verilen seçiciler ile bağlanırlar. Seçiciler bir bir çeşit css element seçicisi gibidir. Eğer `name` yazarsanız bir `etiket` seçmiş olursunuz, `.name` yazarsanız bir `class` seçmiş olursunuz ya da `[name]` yazarsanız bir `property` seçmiş olursunuz.
133 |
134 | `templateUrl` özelliği komponentin arayüz şablonunun konumunu tutar. Bunun yerine `template` özelliğini kullanarak direkt bu dosyaya da html şablon yazabilirsiniz, ihtiyacınıza göre buna siz karar verebilirsiniz.
135 |
136 | ```ts
137 | import { Component } from '@angular/core';
138 |
139 | @Component({
140 | selector: 'app-root',
141 | template: `
142 | hi
143 | `,
144 | styleUrls: ['./app.component.css']
145 | })
146 | export class AppComponent {
147 | }
148 | ```
149 |
150 | `styleUrls` özelliği bize komponentin stil dosyasının konumunu gösterir. Yine yukarıda olduğu gibi `styles` kullanarak da css dosyası kullanmadan direkt olarak bu dosyaya css yazabilirsiniz. Ancak `template` ile `styles` arasında bir fark bulunur, styles bir string dizisi kabul eder, doğrudan string veremezsiniz.
151 |
152 | ```ts
153 | import { Component } from '@angular/core';
154 |
155 | @Component({
156 | selector: 'app-root',
157 | template: `
158 | hi
159 | `,
160 | styles: [
161 | `b {
162 | color: red;
163 | }`
164 | ]
165 | })
166 | export class AppComponent {
167 | }
168 | ```
169 |
170 | `app.component.spec.ts` dosyası testler hakkında işlemler içerir. Şimdilik bunu da erteliyoruz. (Söylemiştim testlerin kaderi bu.)
171 |
172 | Angular projeleri modüller ile çalışır. Bu moduller `java` daki paketlere ya da `c#` daki isim uzaylarına benzerler. Sizin komponentleriniz bir modulde tanımlanır. `app.module.ts` dosyası ana modulu içerir.
173 |
174 |
175 | ```ts
176 | import { BrowserModule } from '@angular/platform-browser';
177 | import { NgModule } from '@angular/core';
178 | import { FormsModule } from '@angular/forms';
179 | import { HttpModule } from '@angular/http';
180 |
181 | import { AppComponent } from './app.component';
182 |
183 | @NgModule({
184 | declarations: [
185 | AppComponent
186 | ],
187 | imports: [
188 | BrowserModule,
189 | FormsModule,
190 | HttpModule
191 | ],
192 | providers: [],
193 | bootstrap: [AppComponent]
194 | })
195 | export class AppModule { }
196 | ```
197 |
198 | Projede kullanılacak tüm komponentler bu dosyada deklare edilmelidir. Eğer burada deklare etmezsek kullandığımız zaman angular bu komponentleri bulamaz.
199 |
200 | Şu anda diğer dosyaları ayrıntılı olarak açıklamak istemiyorum. Bunlara da sonra geleceğiz.
201 |
202 | > Daha derine gitmeden önce typescript öğrenmenizi tavsiye ediyorum. Eğer konu hakkında bilginiz yoksa bi göz atıp sonra buradan devam edin.
203 |
204 |
205 | ### Yeni bir komponent oluşturmak
206 |
207 | Yeni bir komponent oluştururken; önce `./src/app` dizininde bir `server` adında bir klasör oluşturalım.
208 | Bu klasör içinde de `server.component.ts` adında bir dosya oluşturalım. Ayrıca `server.component.html` adında bir dosya daha oluşturmalısınız.
209 |
210 | server.component.ts içinde;
211 |
212 | ```ts
213 | export class ServerComponent {
214 |
215 | }
216 | ```
217 |
218 | `ServerComponent` adında bir sınıf oluşturduk ve sınıfı export ettik. Eğer export etmeseydik bu sınıfı dışarıda kullanamazdık. Hala yapmamız gereken işler var. Bu sınıfı bir komponente çevirecek bir `decorator` oluşturmalıyız. Hadi yapalım o zaman?
219 |
220 | ```ts
221 | @Component({
222 |
223 | })
224 | export class ServerComponent {
225 |
226 | }
227 | ```
228 |
229 | Bu şekilde derlenmeyecektir. Bir şey daha dahil etmeliyiz. `Component` dekoratörü `@angular/core` paketi içinde tanımlı. Bu paketi şu şekilde import edebiliriz.
230 |
231 | ```ts
232 | import { Component } from '@angular/core';
233 |
234 | @Component({
235 |
236 | })
237 | export class ServerComponent {
238 |
239 | }
240 | ```
241 | Artık anguların kullanabileceği bir komponent oluşturmuş durumdayız. Fakat hala geçersiz. Çünkü bir `selector`'e sahip değil. Var olmasına rağmen herhangi bir yerde çağırılmış değil. Bu yüzden ona bir `selector` deklare etmeliyiz.
242 |
243 | ```ts
244 | import { Component } from '@angular/core';
245 |
246 | @Component({
247 | selector: 'app-server'
248 | })
249 | export class ServerComponent {
250 |
251 | }
252 | ```
253 |
254 | `selector` css seçicisi gibidir. Herhangi bir yere direkt olarak `app-server` yazarsanız; `` şeklinde görünecektir. Eğer `.app-server` şeklinde kullanırsanız ``. Hatta `[app-server]` bir özellik(property, attribute) olarak bile kullanabilirsiniz. (şöyle ``).
255 |
256 | Komponentin html dosyasını komponente bağlamalıyız. Bunun için `templateUrl` kullanacağız. Tıpkı `app.component` içinde olduğu gibi.
257 |
258 | ```ts
259 | import {Component} from '@angular/core';
260 |
261 | @Component({
262 | selector: 'app-server',
263 | templateUrl: './server.component.html'
264 | })
265 | export class ServerComponent {
266 |
267 | }
268 | ```
269 |
270 | Bu komponenti kullanabilmek için `app.module.ts` içinde deklare etmeliyiz.
271 |
272 |
273 | ```ts
274 | import { BrowserModule } from '@angular/platform-browser';
275 | import { NgModule } from '@angular/core';
276 | import { FormsModule } from '@angular/forms';
277 | import { HttpModule } from '@angular/http';
278 |
279 | import { AppComponent } from './app.component';
280 | import { ServerComponent } from './server/server.component' // <<-- önce buradan import ediyoruz
281 |
282 | @NgModule({
283 | declarations: [
284 | AppComponent,
285 | ServerComponent // <<-- ardından burada deklarasyonumuza ekliyoruz
286 | ],
287 | imports: [
288 | BrowserModule,
289 | FormsModule,
290 | HttpModule
291 | ],
292 | providers: [],
293 | bootstrap: [AppComponent]
294 | })
295 | export class AppModule { }
296 |
297 | ```
298 |
299 | Şimdi `server.component.html` dosyasını değiştireceğim.
300 |
301 | ```html
302 | server component
303 | ```
304 |
305 | Artık bu komponenti kullanbiliriz. Hemen `app.component.html` içinde kullanalım.
306 |
307 | ```html
308 | app component
309 |
310 |
311 | ```
312 |
313 | Şimdi [http://localhost:8080](http://localhost:8080) adresine bir göz atalım.
314 |
315 | 
316 |
317 | ### Komut satırı ile bir komponent oluşturmak
318 |
319 | Bazen sürekli kendini tekrar eden yapıları üst üste oluşturmak istemeyebiliriz. Bu durum için `@angular/cli`'in bir çözümü var. `ng` nin generate fonksiyonu bize yeni komponentler oluşturmak için yardımcı oluyor.
320 |
321 | ```
322 | ng generate component
323 | or
324 | ng g c
325 | ```
326 |
327 | Eğer bir servers adında bir komponent oluşturmak istersek.
328 |
329 | ```
330 | ng generate component servers
331 | ```
332 |
333 | `app` dizini içine `servers` klasörü oluşturacak, onun da içine `ts`i `html`, `css` ve `.spec.ts` dosyalarını otomatik oluşturacaktır. Ayrıca `app.module.ts` içine bizim yerimize deklarasyon ekleyecek kısaca komponenti direkt olarak kullanıma hazır hale getirecektir.
334 |
335 |
336 | ### Projeye bootstrap css eklemek
337 |
338 | Projemizde Boostrap'e ihtiyaç duyabiliriz. Nasıl import edeceğiz? İlk olarak indirmek zorundayız.
339 |
340 | ```
341 | npm install bootstrap --save
342 | ```
343 |
344 | Ardından `.angular-cli.json` dosyasını açarak şu şekilde düzenlemeliyiz.
345 |
346 | ```js
347 | {
348 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
349 | "project": {
350 | "version": "1.0.0-beta.32.3",
351 | "name": "new-cli"
352 | },
353 | "apps": [
354 | {
355 | "root": "src",
356 | "outDir": "dist",
357 | "assets": [
358 | "assets",
359 | "favicon.ico"
360 | ],
361 | "index": "index.html",
362 | "main": "main.ts",
363 | "polyfills": "polyfills.ts",
364 | "test": "test.ts",
365 | "tsconfig": "tsconfig.json",
366 | "prefix": "app",
367 | "styles": [
368 | "../node_modules/bootstrap/dist/css/bootstrap.min.css", // <<-- bu satırı ekledik
369 | "styles.css"
370 | ],
371 | "scripts": [],
372 | "environmentSource": "environments/environment.ts",
373 | "environments": {
374 | "dev": "environments/environment.ts",
375 | "prod": "environments/environment.prod.ts"
376 | }
377 | }
378 | ],
379 | "e2e": {
380 | "protractor": {
381 | "config": "./protractor.conf.js"
382 | }
383 | },
384 | "lint": [
385 | {
386 | "files": "src/**/*.ts",
387 | "project": "src/tsconfig.json"
388 | },
389 | {
390 | "files": "e2e/**/*.ts",
391 | "project": "e2e/tsconfig.json"
392 | }
393 | ],
394 | "test": {
395 | "karma": {
396 | "config": "./karma.conf.js"
397 | }
398 | },
399 | "defaults": {
400 | "styleExt": "css",
401 | "component": {}
402 | }
403 | }
404 |
405 | ```
406 |
407 | Artık bootstrap kullanıma hazır.
408 |
409 | >**Note:** Bootstrap için bir kütüphane mevcut [bootstrap](https://github.com/ng-bootstrap/ng-bootstrap). Kolayca kullanabileceğimiz bir çok komponent içeriyor.
410 |
411 |
412 | ### Databinding
413 |
414 | Databinding basitçe şablonlar ve sınıflar arasında verilerin bağlanmasını sağlar.
415 |
416 | * **OUT** String Interpolation: Değişkeni şablona bağlar. Yazımı `{{ data }}` şeklindedir.
417 | * **OUT** Property Binding: Bir değişkeni şablonun bir özelliğine atar. Yazımı `[property]="data"` şeklindedir.
418 | * **IN** Olay yakalama: Olayı sınıftaki bir methoda bağlama. Yazımı `(event)="expression"` şeklindedir.
419 |
420 | #### String Interpolation
421 |
422 | Hadi isim yazan basit bir komponent yaratalım. İsim String Interpolation ile bizim sınıfımız içinde tanımlansın.
423 |
424 | ```ts
425 | import { Component } from '@angular/core';
426 |
427 | @Component({
428 | selector: 'app-name',
429 | template: `
430 |
My name is {{name}}
431 | `
432 | })
433 | export class NameComponent {
434 | name: string = "Doğan";
435 | }
436 | ```
437 |
438 | Sonuç:
439 |
440 | 
441 |
442 |
443 | Bu sefer 1 saniyelik bir gecikme ekleyelim. 1 saniyenin ardından ismin Göksel olarak değişeceğini göreceğiz. Ne kadar güzel bir isim.
444 |
445 | ```ts
446 | import { Component } from '@angular/core';
447 |
448 | @Component({
449 | selector: 'app-name',
450 | template: `
451 |
My name is {{name}}
452 | `
453 | })
454 | export class NameComponent {
455 | name: string = "Doğan";
456 |
457 | constructor() {
458 | setTimeout(() => {
459 | this.name = "Göksel";
460 | }, 1000);
461 | }
462 | }
463 | ```
464 |
465 | Başlangıçta bize ` My name is Doğan ` yazmasının 1 saniye sonrasında ` My name is Göksel ` yazısını gördük. Databinding şablonu render etti. Yani render konusunu kafanıza takmayın.
466 |
467 | #### Property binding and Event Binding
468 |
469 | Şimdi diğer databinding(veri bağlama) tiplerini de görelim.
470 |
471 | ```ts
472 | import { Component } from '@angular/core';
473 |
474 | @Component({
475 | selector: 'app-name',
476 | template: `
477 |
478 |
479 | `
480 | })
481 | export class NameComponent {
482 | isDisabled = true;
483 |
484 | someAction() {
485 | alert("hello");
486 | }
487 |
488 | changeDisabled() {
489 | this.isDisabled = !this.isDisabled; // değeri ters çevir
490 | }
491 | }
492 | ```
493 |
494 | Başlangıçta button tıklanamaz durumda. Ancak diğer butona tıkladığımızda artık tıklanabilir duruma geçiyor ve siz butona tıkladığınızda "merhaba" diyen bir alert görüyorsunuz.
495 |
496 | #### Two way databinding
497 |
498 | Angular'da bir databinding tipi daha var. Bu da `Two way databinding` (İki yönlü veri bağlama). Bu sefer olaylar, özellikler ve sınıflar bağlanacak.
499 |
500 | ```ts
501 | import { Component } from '@angular/core';
502 |
503 | @Component({
504 | selector: 'app-name',
505 | template: `
506 |
507 |
508 |
My name is {{name}}
509 | `
510 | })
511 | export class NameComponent {
512 | name: string = "Doğan";
513 | }
514 | ```
515 |
516 | Göreceksiniz input içindeki name özelliği değiştiğinde ` My name is _____ ` kısmı da otomatik olarak yeniden render edilecek. Eğer sınıftaki name özelliğini değiştirirseniz de input içindeki değer değişecektir.
517 |
518 | > **Note:** `ngModel` `app.module.ts` dosyasında import edilmek zorundadır. Gerekli modülün adı `FormsModule`.
519 |
520 | ### Direktifler
521 |
522 | 3 tip direktif var.
523 |
524 | * Komponentler
525 | * Yapısal Direktifler (bunları `*` yıldız karakteri olarak göreceksiniz)
526 | * Özellik Direktifleri
527 |
528 | Komponentleri artık zaten biliyorsunuz. Hadi yapısal direktiflere geçelim.
529 |
530 | Bu direktifler dom'un tamamını kontrol ederler. Neden diye sorabilirsiniz.
531 |
532 | #### ngIf
533 |
534 | Hadi `*ngIf` örneğine bir göz atalım
535 |
536 |
537 | ```ts
538 | import { Component } from '@angular/core';
539 |
540 | @Component({
541 | selector: 'app-name',
542 | template: `
543 |
544 |
545 | I'm visible now
546 |
547 | `
548 | })
549 | export class NameComponent {
550 | visible: boolean = false;
551 | }
552 | ```
553 |
554 | Bu örnekte biz butona tıkladığımızda bir metin beliriyor. Ancak ilginç olan visible değişkeni false olduğunda p elementi henüz yok. Sadece visible değeri true olduğunda yaratılıyor. Yapısal direktifler var olan domu düzenler ya da yok ederler.
555 |
556 | Ayrıca else de (Angular 4) kullanabilirsiniz.
557 |
558 |
559 | ```ts
560 | import { Component } from '@angular/core';
561 |
562 | @Component({
563 | selector: 'app-name',
564 | template: `
565 |
566 |
567 | I'm visible now
568 |
569 |
570 |
571 | I'm hidden
572 |
573 |
574 |
575 | `
576 | })
577 | export class NameComponent {
578 | visible: boolean = false;
579 | }
580 | ```
581 |
582 | Devam etmeden önce lütfen deneyin.
583 |
584 | #### ngFor
585 |
586 | ngFor da yapısal bir direktifdir. Verilen diziye göre kendini düzenler ve kopyalar. Örneğin;
587 |
588 | ```ts
589 | import { Component } from '@angular/core';
590 |
591 | @Component({
592 | selector: 'app-name',
593 | template: `
594 |
595 |
{{car}}
596 |
597 | `
598 | })
599 | export class NameComponent {
600 | cars = [
601 | 'Toyota',
602 | 'Honda',
603 | 'Ford'
604 | ]
605 | }
606 | ```
607 |
608 | 
609 |
610 | ngFor ayrıca index'e de sahiptir. Eğer `;` bu kapsamda kullanabileceğiniz bir index değişkeni tanımlayabilirsiniz.
611 |
612 | ```ts
613 | import { Component } from '@angular/core';
614 |
615 | @Component({
616 | selector: 'app-name',
617 | template: `
618 |
1457 | ```
1458 |
1459 | routerLinkActive direktifi `routerLinkActiveOptions` adında başka bir direktife sahiptir. Bu routerLinkActiveOptions direktifiyle birlikte ek opsiyonlar verebiliriz. Örneğin tam path doğrulaması:
1460 |
1461 | ```html
1462 |