diff --git a/.gitbook/assets/angular.png b/.gitbook/assets/angular.png new file mode 100644 index 0000000..c510293 Binary files /dev/null and b/.gitbook/assets/angular.png differ diff --git a/.gitbook/assets/lab (1).jpg b/.gitbook/assets/lab (1).jpg new file mode 100644 index 0000000..552d90b Binary files /dev/null and b/.gitbook/assets/lab (1).jpg differ diff --git a/.gitbook/assets/lab.jpg b/.gitbook/assets/lab.jpg new file mode 100644 index 0000000..552d90b Binary files /dev/null and b/.gitbook/assets/lab.jpg differ diff --git a/.gitbook/assets/nggirls-banner-transparent (1).png b/.gitbook/assets/nggirls-banner-transparent (1).png new file mode 100644 index 0000000..a1b4b43 Binary files /dev/null and b/.gitbook/assets/nggirls-banner-transparent (1).png differ diff --git a/.gitbook/assets/nggirls-banner-transparent (2).png b/.gitbook/assets/nggirls-banner-transparent (2).png new file mode 100644 index 0000000..a1b4b43 Binary files /dev/null and b/.gitbook/assets/nggirls-banner-transparent (2).png differ diff --git a/.gitbook/assets/nggirls-banner-transparent.png b/.gitbook/assets/nggirls-banner-transparent.png new file mode 100644 index 0000000..a1b4b43 Binary files /dev/null and b/.gitbook/assets/nggirls-banner-transparent.png differ diff --git a/.gitbook/assets/slogen (1).png b/.gitbook/assets/slogen (1).png new file mode 100644 index 0000000..9f0dd40 Binary files /dev/null and b/.gitbook/assets/slogen (1).png differ diff --git a/.gitbook/assets/slogen (2).png b/.gitbook/assets/slogen (2).png new file mode 100644 index 0000000..9f0dd40 Binary files /dev/null and b/.gitbook/assets/slogen (2).png differ diff --git a/.gitbook/assets/slogen.png b/.gitbook/assets/slogen.png new file mode 100644 index 0000000..9f0dd40 Binary files /dev/null and b/.gitbook/assets/slogen.png differ diff --git a/README.md b/README.md index 702f000..4a5d66c 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,20 @@ -# Angular Tutorial for Beginners - +# About -# Creating a Todo-List App +## Angular Tutorial for Beginners - + +## Creating a Todo-List App This tutorial will take you step by step on how to create your own todo list application using Angular \(version 2 and above\). Through the tutorial, we'll be using the Angular-CLI, save data in the local storage and deploy the code to Github Pages. +#### [StackBlitz version - use an online editor](https://ng-girls.gitbook.io/todo-list-tutorial/v/stackblitz/) + This tutorial is open source and is written by the community. Please feel free to send any suggestions and pull requests. Special thanks to the members of** Angular AfterHours meetup group **for kickstarting this tutorial during a [special meetup event](http://www.meetup.com/Angular-AfterHours/events/235151422/)! -The tutorial is used in the [ngGirls](http://ng-girls.org) workshops. You are welcome to use it in your own workshop and we'd love to hear about it! - write us to: [info@ng-girls.org](/mailto:info@ng-girls.org). +The tutorial is used in the [ngGirls](http://ng-girls.org) workshops. You are welcome to use it in your own workshop and we'd love to hear about it! - write us to: [info@ng-girls.org](mailto:info@ng-girls.org). -![](/assets/ngGirls banner transparent.png) +![](.gitbook/assets/nggirls-banner-transparent%20%281%29.png) -![](/assets/slogen.png) +![](.gitbook/assets/slogen.png) **About the lead author:** Shmuela Jacobs is a senior front-end developer and consultant mastering Angular. During her academic studies \(M.Sc. in Information Management Engineering and B.Sc. in Physics\) she has combined her passions of coding and teaching as a software developer, teaching assistant, science museum guide, and researcher. Today she continues to enjoy these activities as a full-time front end developer, sharing her knowledge and experience in meetups and conferences. Shmuela is the founder of ngGirls and the organizer of Angular AfterHours meetup group. diff --git a/SUMMARY.md b/SUMMARY.md index 13e1f50..cc0e7dc 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,27 +1,27 @@ -# Summary +# Table of contents * [About](README.md) * [Introduction](introduction.md) * [Installations](installations.md) -* [Angular kicks in](angular_kicks_in.md) +* [Angular kicks in](angular-kicks-in.md) * [Component](component.md) -* [A new component](a_new_component.md) +* [A new component](a-new-component.md) * [Class](class.md) -* [Property binding](property_binding.md) -* [Event binding](event_binding.md) -* [Element ref - \#](element_ref_-.md) -* [The To Do list](the_list.md) -* [New component: todo-item](new_component_todo-item.md) -* [Add items](add_items.md) -* [Refactor App Component](refactor_app_component.md) -* [Adding Style](adding_style.md) +* [Property binding](property-binding.md) +* [Event binding](event-binding.md) +* [Element ref - \#](element-ref.md) +* [The To Do list](the-to-do-list.md) +* [New component: todo-item](new-component-todo-item.md) +* [Add items](add-items.md) +* [Refactor App Component](refactor-app-component.md) +* [Adding Style](adding-style.md) * [Service](service.md) -* [Add more abilities to service](add_more_abilities_to_service.md) -* [Local storage](local_storage.md) -* [Remove item](remove_item.md) -* [Adding a checkbox](adding_a_checkbox.md) -* [Deploy to GithubPages](deploy_to_githubpages.md) -* [Enrich the todo-item component](enrich_the_todo-item_component.md) -* [Appendix 1: Generating a new project](generating_a_new_project.md) +* [Add more abilities to service](add-more-abilities-to-service.md) +* [Local storage](local-storage.md) +* [Remove item](remove-item.md) +* [Adding a checkbox](adding-a-checkbox.md) +* [Deploy to GithubPages](deploy-to-githubpages.md) +* [Enrich the todo-item component](enrich-the-todo-item-component.md) +* [Appendix 1: Generating a new project](appendix-1-generating-a-new-project.md) * [Appendix 2: Tutorial Extensions](appendix-2-tutorial-extensions.md) diff --git a/a_new_component.md b/a-new-component.md similarity index 68% rename from a_new_component.md rename to a-new-component.md index d5fef71..0579ac1 100644 --- a/a_new_component.md +++ b/a-new-component.md @@ -1,38 +1,37 @@ # A new component -In this chapter we will write a whole new component. It will allow us adding an item to the todo list. It will be composed of the HTML elements `input` and `button`. We will call it Input-Button-Unit. +In this chapter we will write a whole new component. It will allow us adding an item to the todo list. It will be composed of the HTML elements `input` and `button`. We will call it Input-Button-Unit. We'll use Angular-CLI to generate all the needed files and boilerplate for us. Angular-CLI takes commands in a terminal window. This doesn't mean that we have to stop the process `ng serve`. Instead, we can open another terminal window or tab and run the additional commands from there. The changes will be reflected immediately in the browser. Open another terminal tab and run: -```cmd +```text ng g c input-button-unit ``` As we've seen before, `ng` is the command for using Angular-CLI. `g` is a shorthand for `generate`. `c` is a shorthand for `component`. `input-button-unit` is the name we give to the component. -So the long version of the command is (don't run it): +So the long version of the command is \(don't run it\): -``` +```text ng generate component input-button-unit ``` Let's take a look of what Angular-CLI created for us. -It created a new folder called `src/app/input-button-unit`. There are three files there (or four if you're not using inline-template): +It created a new folder called `src/app/input-button-unit`. There are three files there \(or four if you're not using inline-template\): * `input-button-unit.component.css` - this is where the style that's specific to the component will be placed. * `input-button-unit.component.spec.ts` - this is a file for testing the component. We will not deal with it in this tutorial. * `input-button-unit.component.ts` - this is the component file where we will define its logic. * `input-button-unit.component.html` - this is the HTML template file, if you're not using inline-template. - Open the file `input-button-unit.component.ts`. You can see that Angular-CLI has generated the component's configuration for us, including its selector, which is the name we gave preceded by the prefix `app`, and a default template: -```ts -// src/app/input-button-unit/input-button-unit.component.ts - +{% code-tabs %} +{% code-tabs-item, title="src/app/input-button-unit/input-button-unit.component.ts" %} +```typescript @Component({ selector: 'app-input-button-unit', template: ` @@ -43,18 +42,20 @@ Open the file `input-button-unit.component.ts`. You can see that Angular-CLI has styleUrls: ['./input-button-unit.component.css'] }) ``` +{% endcode-tabs-item %} +{% endcode-tabs %} -> The prefix `app` will be added to the component selector of all the components you will generate. This is to avoid name conflicts with other components and HTML elements. For instance, if you create a component named input it will not conflict with HTML's `` element, since its selector will be `app-input`. - ->`app` is the default prefix, which is good for your main application. However, if you're writing a library of components to be used in other projects, you should choose a different prefix. For example, the [Angular Material](https://material.angular.io/) library uses the prefix `mat`. You can create a project stating the prefix of your choice using the flag `--prefix`, or change it afterwards in the file `.angular-cli.json`. +> The prefix `app` will be added to the component selector of all the components you will generate. This is to avoid name conflicts with other components and HTML elements. For instance, if you create a component named input it will not conflict with HTML's `` element, since its selector will be `app-input`. +> +> `app` is the default prefix, which is good for your main application. However, if you're writing a library of components to be used in other projects, you should choose a different prefix. For example, the [Angular Material](https://material.angular.io/) library uses the prefix `mat`. You can create a project stating the prefix of your choice using the flag `--prefix`, or change it afterwards in the file `.angular-cli.json`. We can use this component as is and see the result! -Open the root component file, `app.component.ts` and add the app-input-button-unit tag anywhere inside the template (remember we refactored the root component to have an inline template): - -```html -// src/app/app.component.ts +Open the root component file, `app.component.ts` and add the app-input-button-unit tag anywhere inside the template \(remember we refactored the root component to have an inline template\): +{% code-tabs %} +{% code-tabs-item, title="src/app/app.component.ts" %} +```markup template: `

{{ title }} @@ -63,32 +64,37 @@ template: ` `, ``` +{% endcode-tabs-item %} +{% endcode-tabs %} Check what's new in the browser! Let's add some content in our new component. First, add a `title` member which we will use as the todo item's title: -```ts -// src/app/input-button-unit/input-button-unit.component.ts - +{% code-tabs %} +{% code-tabs-item, title="src/app/input-button-unit/input-button-unit.component.ts" %} +```typescript export class InputButtonUnitComponent implements OnInit { title = 'Hello World'; - ... ``` +{% endcode-tabs-item %} +{% endcode-tabs %} It will not interfere with the `app-root` component's `title`, since each component's content is encapsulated within it. Next, add some content and an interpolation of the title member in the template: -```html -// src/app/input-button-unit/input-button-unit.component.ts - +{% code-tabs %} +{% code-tabs-item, title="src/app/input-button-unit/input-button-unit.component.ts" %} +```markup template: `

The title is: {{ title }}

`, ``` +{% endcode-tabs-item %} +{% endcode-tabs %} Check out the result! diff --git a/add_items.md b/add-items.md similarity index 95% rename from add_items.md rename to add-items.md index 748f190..1fbdb4d 100644 --- a/add_items.md +++ b/add-items.md @@ -2,29 +2,29 @@ We want to add items to our list. With Angular we can do this easily and see the item added immediately. We will do this from within the `inputComponent` we created before. We'll change it so when hitting the Enter key or clicking the submit button, the value of the input box will become the title of the new item. And the new item will be added to the list. -But we don't want the todo-input component to be responsible for adding a new item for the list. We want it to have minimal responsibility, and **delegate the action to its parent component**. One of the advantages of this approach is that this component will be reusable, and can be attached to a different action in different situations. +But we don't want the todo-input component to be responsible for adding a new item for the list. We want it to have minimal responsibility, and **delegate the action to its parent component**. One of the advantages of this approach is that this component will be reusable, and can be attached to a different action in different situations. For example, in our case, we'll be able to use the `inputComponent` inside the `itemComponent`. Then we'll have an input box for each item and we'll be able to edit the item's title. In this case, pressing the Enter key or the save button will have a different effect. So what we actually want to do is to **emit an event** from the todo-input component whenever the title is changed. With Angular we can easily define and emit events from our components! -## @Output() +## @Output\(\) Inside the `inputComponent` class add the following line, which defines an output for the component. -```ts +```typescript @Output() submit: EventEmitter = new EventEmitter(); ``` -The output property is called `submit`. Make sure that Output and EventEmitter are added to the import declaration in the first line of the file: +The output property is called `submit`. Make sure that Output and EventEmitter are added to the import declaration in the first line of the file: -```ts +```typescript import { Component, OnInit, Output, EventEmitter } from '@angular/core'; ``` Now, whenever we call `this.submit.emit()` an event will be emitted to the parent component. Let's call it in the changeTitle method: -```ts +```typescript changeTitle(newTitle: string): void { this.submit.emit(newTitle); } @@ -38,13 +38,13 @@ Nothing else is changed in the todo-input component. The events emitted from `ke Now all we need to do is catch the event in the parent component and attach logic to it. Go to the app-root component and bind to the `submit` event in the `` component: -```html +```markup ``` Now all that left is to implement the `addItem` method, which receives a string and adds it to the list: -```ts +```typescript addItem(title: string): void { this.todoList.push({ title }); } diff --git a/add_more_abilities_to_service.md b/add-more-abilities-to-service.md similarity index 58% rename from add_more_abilities_to_service.md rename to add-more-abilities-to-service.md index 776855a..55e9147 100644 --- a/add_more_abilities_to_service.md +++ b/add-more-abilities-to-service.md @@ -1,26 +1,29 @@ # Add more abilities to service -# In this chapter we would improve our service by adding more abilities. +## Add more abilities to service + +## In this chapter we would improve our service by adding more abilities. First, lets open our app's service file which is available at - `app/todo-list.service.ts` There we'll add a new function to the service, called `addItem`, like so: + ```javascript addItem(item): void { this.todoList.push({ item }); -} +} ``` This will allow us to call the same function from everywhere across the application thus making our app more easy to maintain. -And now we can change our code in `app/list-manager/list-manager.component.ts` to call the `addItem` function directly from the service like so: +And now we can change our code in `app/list-manager/list-manager.component.ts` to call the `addItem` function directly from the service like so: ```javascript addItem(item): void { this.todoListService.addItem(item); -} +} ``` -- There may be additional logic when calling these methods, i.e. saving the changes in the DB (we will implement it later on) -- A better way to handle data is using immutable objects, then there will be no binding - the references will change (but we won’t implement redux in this tutorial at the moment) +* There may be additional logic when calling these methods, i.e. saving the changes in the DB \(we will implement it later on\) +* A better way to handle data is using immutable objects, then there will be no binding - the references will change \(but we won’t implement redux in this tutorial at the moment\) diff --git a/adding_a_checkbox.md b/adding-a-checkbox.md similarity index 61% rename from adding_a_checkbox.md rename to adding-a-checkbox.md index 272227c..14fe0ee 100644 --- a/adding_a_checkbox.md +++ b/adding-a-checkbox.md @@ -1,4 +1,4 @@ -# Adding A Checkbox +# Adding a checkbox We are now able to interact with our todo list by removing items. But what if we want to complete items and still be able to see them on our list, for example, have a line-strike through the todo title? Enter the checkbox! @@ -11,17 +11,19 @@ We will look at: Let's go ahead and add a checkbox into our item.component.ts file. Place the following code right before the `

` tag containing `{{ todoItem.title}}`: -```html +```markup ``` -Now, in order for the checkbox to do anything we need to add a click event which we will call completeItem(). Let's do that now: -```html +Now, in order for the checkbox to do anything we need to add a click event which we will call completeItem\(\). Let's do that now: + +```markup ``` -When we click on the checkbox it will run the completeItem() function. Let's talk about what this function needs to accomplish. We want to be able to toggle some CSS styling on the todo title so that when the checkbox is checked it will have a line-strike through it, and no line-strike when unchecked. In order to achieve this we will toggle a variable to be either true or false to represent checked or unchecked states. Add the following code to the ItemComponent class: -```js +When we click on the checkbox it will run the completeItem\(\) function. Let's talk about what this function needs to accomplish. We want to be able to toggle some CSS styling on the todo title so that when the checkbox is checked it will have a line-strike through it, and no line-strike when unchecked. In order to achieve this we will toggle a variable to be either true or false to represent checked or unchecked states. Add the following code to the ItemComponent class: + +```javascript isComplete: boolean = false; completeItem() { @@ -29,17 +31,17 @@ completeItem() { } ``` -But wait! How is any of this going to affect the todo title when we're only touching the checkbox??? Well, Angular2 has this wonderful directive called NgClass. This directive applies or removes a class based on a boolean value (true or false). There are many ways to use this directive(see documentation: https://angular.io/docs/ts/latest/api/common/index/NgClass-directive.html) but we will focus on using it like so: +But wait! How is any of this going to affect the todo title when we're only touching the checkbox??? Well, Angular2 has this wonderful directive called NgClass. This directive applies or removes a class based on a boolean value \(true or false\). There are many ways to use this directive\(see documentation: [https://angular.io/docs/ts/latest/api/common/index/NgClass-directive.html](https://angular.io/docs/ts/latest/api/common/index/NgClass-directive.html)\) but we will focus on using it like so: -```html +```markup ... ``` -The 'first' and 'second' class will be applied to the element because they are given a true value, whereas, the 'third' class will not be applied because it is given a false value. So this is where our earlier code comes into play. Our completeItem() function will toggle between true and false values, thus dictating whether a class should be applied or removed. +The 'first' and 'second' class will be applied to the element because they are given a true value, whereas, the 'third' class will not be applied because it is given a false value. So this is where our earlier code comes into play. Our completeItem\(\) function will toggle between true and false values, thus dictating whether a class should be applied or removed. Let's add this NgClass directive to our todo title now: -```html +```markup

{{ todoItem.title }}

@@ -54,3 +56,4 @@ And finally, add the css to our item.component.css file ``` Voila! Checking the checkbox should apply a line through the todo title, and unchecking the checkbox should remove the line. + diff --git a/adding_style.md b/adding-style.md similarity index 80% rename from adding_style.md rename to adding-style.md index 8c0fd3b..6850475 100644 --- a/adding_style.md +++ b/adding-style.md @@ -6,7 +6,7 @@ We can also state general style rules to be used across the application. This is Angular gives us different style encapsulation methods, but we'll stick to the default. -Angular-CLI has generated a general stylesheet for us at `src/style.css`. Paste the following code into this file: +Angular-CLI has generated a general stylesheet for us at `src/style.css`. Paste the following code into this file: ```css html, body, div, span, @@ -48,28 +48,28 @@ ol, ul { .btn:hover { background: lightslategrey; } - ``` ->How does the project know to look at this file? In Angular-CLI configuration file `.angular-cli.json` under `apps[0].styles` you can state the files for the build tool to take and add to the project. You can open the browser's dev tools and see the style inside the element: -```html - - ... - - ... - - ... - - ... - -``` - - -Now lets add style specifically to the list-manager component. +> How does the project know to look at this file? In Angular-CLI configuration file `.angular-cli.json` under `apps[0].styles` you can state the files for the build tool to take and add to the project. You can open the browser's dev tools and see the style inside the element: +> +> ```markup +> +> ... +> +> ... +> +> ... +> +> ... +> +> ``` + +Now lets add style specifically to the list-manager component. Open the file `list-manager.component.css` and paste the following style inside: + ```css .todo-app { position: relative; @@ -125,10 +125,10 @@ Open the file `list-manager.component.css` and paste the following style inside: } ``` -How does this stylesheet gets attached to the `list-manager` component? -Look at the file `list-manager.component.ts`. One of the properties in the object passed to the `@Component` decorator is `styleUrls`. It's a list of stylesheets to be used by Angular, which encapsulates the style within the component. +How does this stylesheet gets attached to the `list-manager` component? Look at the file `list-manager.component.ts`. One of the properties in the object passed to the `@Component` decorator is `styleUrls`. It's a list of stylesheets to be used by Angular, which encapsulates the style within the component. Add the following style to `input.component.css`: + ```css .todo-input { padding: 4px 10px 4px; @@ -148,6 +148,7 @@ Add the following style to `input.component.css`: ``` Add the following style to `item.component.css`: + ```css .todo-item { padding: 10px 0; @@ -175,16 +176,19 @@ Add the following style to `item.component.css`: .btn-red:hover { background: darkred; } - ``` + Note: Don't forget to put the CSS-classes to the template-code of your specified component like this: -```ts + +```typescript @Component({ ... template: `

The title is: {{ title }}

- `, - + `, ``` Now we can use the value that the user entered in the input element in the method called when clicking the Save button! @@ -65,10 +64,14 @@ Instead of hunting down the elements via DOM query \(which is bad practice as we Next on, we'll build the list of todo items. ### Tip - explore the element reference + Just like we did in the previous chapter, when we logged $event, you can do the same with `#inputElement`. -![lab-icon](/assets/lab.jpg) **Playground:** Change the method `changeTitle` so it will receive the whole element reference and log it to the console: -```html +![lab-icon](.gitbook/assets/lab%20%281%29.jpg) + + **Playground:** Change the method `changeTitle` so it will receive the whole element reference and log it to the console: + +```markup @@ -77,12 +80,12 @@ Just like we did in the previous chapter, when we logged $event, you can do the Save ``` -```ts + +```typescript changeTitle(inputElementRef) { console.log(inputElementRef); this.title = inputElementRef.value; } - ``` ## Resources diff --git a/enrich_the_todo-item_component.md b/enrich-the-todo-item-component.md similarity index 94% rename from enrich_the_todo-item_component.md rename to enrich-the-todo-item-component.md index 9671493..160de63 100644 --- a/enrich_the_todo-item_component.md +++ b/enrich-the-todo-item-component.md @@ -1,2 +1,4 @@ # Enrich the todo-item component + + diff --git a/event_binding.md b/event-binding.md similarity index 92% rename from event_binding.md rename to event-binding.md index f1bf754..55744b4 100644 --- a/event_binding.md +++ b/event-binding.md @@ -8,7 +8,7 @@ We still don't have a whole list to show, but at the moment we will use another First, let's implement `changeTitle`. You can replace `generateTitle` with this new method. It will receive the new title as its argument. The best practice is to have our custom methods written after the lifecycle methods \(\`ngOnInit\` in this case\): -```ts +```typescript // src/app/input-button-unit/input-button-unit.component.ts changeTitle(newTitle: string) { @@ -22,7 +22,7 @@ Just like binding to element properties, we can bind to events that are emitted Let's try a simple example, where the title is changed when the user clicks on the button. Notice the parenthesis around `click`. \(We also change the binding of the input's value back to `title`.\) -```html +```markup // src/app/input-button-unit/input-button-unit.component.ts template: ` @@ -34,7 +34,7 @@ template: ` `, ``` -The event is called `click` and not `onClick` - in Angular you remove the `on` prefix from the events in the elements. +The event is called `click` and not `onClick` - in Angular you remove the `on` prefix from the events in the elements. Go to the browser and see the result - click on the Save button. @@ -49,7 +49,7 @@ But now we'll bind a method to an event on the input element: when the user clic When the user types, keyboard events are emitted. For example `keydown` and `keyup`. We will catch the `keyup` event \(when the pressed key is released\) and change the title: -```html +```markup ``` @@ -57,7 +57,7 @@ Now when the user types in the input box, the title is changed to "Button Clicke **Tip:** When an element becomes long due to its attributes, you should make it easier on the eye by splitting it into several lines: -```html +```markup ``` @@ -68,7 +68,7 @@ Now we just react when the `keyup` event occurs. Angular allows us to get the ev The event object emitted on `keyup` events has a reference to the element that emitted the event - the input element. The reference is kept in the event's property `target`. As we've seen before, the input element has a property `value` which holds the current string that's in the input box. We can pass `$event.target.value` to the method: -```html +```markup ``` @@ -79,7 +79,7 @@ Check it out in the browser. Now with every key stroke, you can see the title ch You can limit the change to only a special key stroke, in our case it's the Enter key. Angular makes it really easy for us. The `keyup` event has properties which are more specific events. So just add the name of the key you'd like to listen to: -```html +```markup ``` @@ -88,11 +88,13 @@ Now the title will change only when the user hits the Enter key while typing in ### Tip - explore the $event -![lab-icon](/assets/lab.jpg) **Playground: **You can change the changeTitle method to log the `$event` object in the console. This way you can explore it and see what properties it has. +![lab-icon](.gitbook/assets/lab%20%281%29.jpg) + + **Playground: **You can change the changeTitle method to log the `$event` object in the console. This way you can explore it and see what properties it has. Change the method `changeTitle`: -```ts +```typescript changeTitle(event): void { console.log(event); this.title = event.target.value; // the original functionality still works @@ -101,7 +103,7 @@ changeTitle(event): void { Now change the argument you're passing in the template, to pass the whole `$event`: -```html +```markup ``` diff --git a/installations.md b/installations.md index 90d0477..11ebf8f 100644 --- a/installations.md +++ b/installations.md @@ -1,4 +1,4 @@ -# Installation +# Installations Every developer needs a set of tools and libraries to start working. In our case, we'll install all the necessary tools, and once we have our Angular-CLI installed it will take care of additional libraries we'll need the for current and future projects. @@ -10,7 +10,7 @@ Our first tool is the **browser**. We'll use it to see the result of our work an ### IDE -Our next tool is the **IDE** - integrated development environment. It's a software that helps you write the code. IDEs can do a lot of amazing things such as: +Our next tool is the **IDE** - integrated development environment. It's a software that helps you write the code. IDEs can do a lot of amazing things such as: * paint the code so it's easier to identify expressions * suggest completions to what you type @@ -51,13 +51,13 @@ Another tool which most web developers are using is **NodeJS**. Once installed, NodeJS lets you run JavaScript code on your computer. It is used to run a local server which serves the project files to the browser and simulates a real running website. -NPM allows you to easily download and install different libraries from the internet and manage their versions. +NPM allows you to easily download and install different libraries from the internet and manage their versions. Download NodeJS [here](https://nodejs.org/en/). If you already have NodeJS installed, make sure you check that the version is 6.9.0 or above by running this in your command line / terminal: -``` +```text node -v ``` @@ -67,7 +67,7 @@ If it's lower than required, download the new version from the website and insta Once installed, you should also have NPM installed. Check its version by running: -``` +```text npm -v ``` @@ -75,7 +75,7 @@ npm -v [Angular-CLI](https://github.com/angular/angular-cli) is a powerful tool that simplifies a lot of the development process. It also installs libraries you'll use in your current and future projects. Install it by running: -``` +```text npm i -g @angular/cli ``` @@ -89,13 +89,13 @@ Read more about Angular-CLI in the following section. First, create a folder to store all your projects, for example _myProjects_, and then go into the folder, using a terminal \(command line window\): -``` +```text cd the-path-to-your-folder/myProjects ``` Now, create a new project, called _todo-list_ inside the projects folder, using Angular-CLI, by running the following command: -``` +```text ng new todo-list ``` @@ -103,13 +103,13 @@ This can take a while, since many packages are being downloaded from the web and Now enter the new folder that Angular-CLI created for this project: -``` +```text cd todo-list ``` Once inside the folder of the application, run the application by using the following command: -``` +```text ng serve -o ``` diff --git a/introduction.md b/introduction.md index 3c113e4..eb088de 100644 --- a/introduction.md +++ b/introduction.md @@ -2,7 +2,7 @@ Angular is much more than a framework. It's a whole platform for creating applications that can run not only on a browser, but anywhere. It gives you tools to advanced capabilities, such as easily creating dynamic components, routes definitions and much more. -![](/assets/angular.png) +![](.gitbook/assets/angular.png) In this tutorial you'll learn how to develop a basic application using Angular. You will get to know the building blocks to have a working application: modules, components and services. Angular-CLI will help you in the process in many ways and will simplify the development process. @@ -10,7 +10,7 @@ By the end of this tutorial, you'll have a ready todo-list application, that sho The list is saved in the browser's local storage. All the changes will remain even when you refresh the browser or even turn off your computer \(as long as you use the same browser on the same computer and not in private mode\). -You will even publish the application on the Web, so that other could use it! +You will even publish the application on the Web, so that others could use it! After completing this tutorial, we encourage you to continue developing the application and adding your personal touch. diff --git a/local_storage.md b/local-storage.md similarity index 91% rename from local_storage.md rename to local-storage.md index ea848cd..37b8d54 100644 --- a/local_storage.md +++ b/local-storage.md @@ -2,8 +2,7 @@ ## What is local storage? -Local storage, as its name implies, is a tool for storing data locally. -As similar to cookies, local storage stores the data on the user's computer, and by that it lets us, as developers, a quick way to access this data for both reading and writing. +Local storage, as its name implies, is a tool for storing data locally. As similar to cookies, local storage stores the data on the user's computer, and by that it lets us, as developers, a quick way to access this data for both reading and writing. ## Browser support @@ -19,7 +18,7 @@ Local storage stores the data in a form of key-value, so the interface is quite- An example usage: -``` +```text localStorage.setItem('name','Mor'); let name = localStorage.getItem('name'); @@ -37,13 +36,13 @@ There are a few more wonderful methods you can use, as described [here](https:// In the following section we will build a local storage service that later on will be used to store our todo list items. As described in earlier tutorials, we will generate the service using `angular-cli`: -``` +```text ng g s todo-list-storage ``` The new file `todo-list-storage.service.ts`, should be created with the following code: -``` +```text import { Injectable } from '@angular/core'; @Injectable() @@ -54,15 +53,17 @@ export class TodoListStorageService { } ``` -**If something looks unfamiliar/odd to you, please refer to the [Service tutorial](https://shmool.gitbooks.io/todo-list-tutorial/content/service.html) for more detailed information about services.** +**If something looks unfamiliar/odd to you, please refer to the **[**Service tutorial**](https://shmool.gitbooks.io/todo-list-tutorial/content/service.html)** for more detailed information about services.** We need to provide the service in our ngModule. Open `app.module.ts` and in the `providers` list add the new class: -```ts + +```typescript providers: [TodoListService, TodoListStorageService], ``` + Make sure the class is also imported into the file: -```ts +```typescript import { TodoListStorageService } from './todo-list-storage.service'; ``` @@ -75,20 +76,20 @@ In addition, let's add a constant that will store the name of the key we want to `const storageName = 'aah_todo_list';` Now we want to initiliaze this property with data, by retriving it from localStorage, so within the constructor, add: -```ts + +```typescript constructor() { this.todoList = JSON.parse(localStorage.getItem(storageName)); } ``` -Wait! Wait! Why `JSON.parse`? The answer is simple: -As described earlier in this tutorial, local storage stores data in a form of key-value, that means that the values are stored as **strings**. +Wait! Wait! Why `JSON.parse`? The answer is simple: As described earlier in this tutorial, local storage stores data in a form of key-value, that means that the values are stored as **strings**. So, if we want to have a real object to deal with, we must parse the strign into a valid object. Now lets start doing some real stuff, but first we will declare all the public methods we want to expose in this service, which are **get, post, put**, and **destroy**. Our service should now look similiar to: -``` +```text import { Injectable } from '@angular/core'; const storageName = 'aah_todo_list'; @@ -123,7 +124,7 @@ We will now implement them one by one. This method will simply return the current state of items stored in the service: -``` +```text /** * Get items * @returns {any[]} @@ -140,7 +141,7 @@ If you are not familiar with the `...` operator, please refer to [this documenta This method will be responsible for adding a new item, and returning the new list. It accepts one parameter, `item` which will be the item to add: -``` +```text /** * Add a new todo item * @param item @@ -152,13 +153,13 @@ It accepts one parameter, `item` which will be the item to add: } ``` -Some of you might notice that we just pushed a new item to the array. +Some of you might notice that we just pushed a new item to the array. But what about the local storage? We must also synchronize it with the new array! Lets add a new **private** method in our service, which will be used internaly to update the stored list: -``` +```text /** * Synchronize the local storage with the current list * @returns {any[]} @@ -176,7 +177,7 @@ After we updated the value, we simply return the new list using the `get` method Now we need to modify our `post` function to use `update` so everyhing is synchronized in harmony: -``` +```text /** * Add a new todo item * @param item @@ -193,7 +194,7 @@ Now we need to modify our `post` function to use `update` so everyhing is synchr Here we want to update an existing item. Before that, let's add another helper private method `findItemIndex`, which will simply return the index of an item with the list array: -``` +```text /** * Find the index of an item in the array * @param item @@ -206,7 +207,7 @@ Before that, let's add another helper private method `findItemIndex`, which will Now, we can use `Object.assign` to update an existing item: -``` +```text /** * Update an existing item * @param item @@ -219,7 +220,7 @@ Now, we can use `Object.assign` to update an existing item: } ``` -So what is going on here? +So what is going on here? `Object.assign` takes a target object \(first argument\) and source objects \(all the rest of the argument\), and copies to the target object. If a property existing on both target and source, this method will replace the old value with the new one. Here we want to update an item in the list, so first we find it's index in the array, and then apply the changes on it. @@ -229,7 +230,7 @@ At the end, we want to synchronize the local storage \(`this.update`\) and retur This method will remove an item from the list and then synchronize with local storage: -``` +```text /** * Remove an item from the list * @param item @@ -247,10 +248,10 @@ In our code, we first find the index of the item to remove, and remove only it \ ## Add some default data -Lets assume we want our todo list always have some default data to start with. +Lets assume we want our todo list always have some default data to start with. Then we can add it by modifying our service, by adding in the constants section \(after the imports\): -``` +```text const defaultList = [ { title: 'install NodeJS' }, { title: 'install Angular CLI' }, @@ -263,7 +264,7 @@ const defaultList = [ And then modify our constructor: -``` +```text constructor() { this.todoList = JSON.parse(localStorage.getItem(storageName)) || defaultList; } @@ -273,7 +274,7 @@ The above will make sure that if data was not yet set to localStorage, our servi ## Almost done! -Our service is now ready for work! +Our service is now ready for work! But wait, we need to provide it, in order to use it. Open `app.module.ts` and add `TodoListStorageService` to the `providers` array. @@ -287,7 +288,7 @@ First we need to import the new service: Then, we need to inject it in the constructor so we will have an instance to work with: -``` +```text constructor(private storage:TodoListStorageService) { } ``` @@ -298,7 +299,7 @@ Let's also modify the current methods: **Before** -``` +```text getTodoList() { return this.todoList; } @@ -310,7 +311,7 @@ addItem(item) { **After** -``` +```text getTodoList() { return this.storage.get(); } @@ -322,7 +323,7 @@ addItem(item) { Now we have one last modification to make. Open up `list-manager.component.ts`, and let's modify `addItem` method this way: -``` +```text addItem(title:string) { this.todoList = this.todoListService.addItem({ title }); } diff --git a/new_component_todo-item.md b/new-component-todo-item.md similarity index 55% rename from new_component_todo-item.md rename to new-component-todo-item.md index cc3ad15..1ad9382 100644 --- a/new_component_todo-item.md +++ b/new-component-todo-item.md @@ -2,45 +2,54 @@ We will create a new component which will be used for each todo item that is displayed on the list. It will be a simple component at first, but it will grow later on. What's important is that **it will get the todo item as an input from its parent component**. This way it can be a reusable component, and not rely directly on the application's data and state. -Create a new component called `item`: +Create a new component called `item`: -``` +```text ng g c todo-item ``` -You can see a new folder was created - `src/app/todo-item`, with the component files inside. - -Use the new component in the template of `appComponent` - inside the `
  • ` element: +You can see a new folder was created - `src/app/todo-item`, with the component files inside. -```html -// src/app/app.component.ts +Use the new component in the template of `app-root` component - inside the `
  • ` element: +{% code-tabs %} +{% code-tabs-item, title="src/app/app.component.ts" %} +```markup
    ``` +{% endcode-tabs-item %} +{% endcode-tabs %} Check out the result in the browser. What do you see? Why? -## @Input() -We want to display the title of each item from within the `todo-item` component. We need to pass the title of the current item in the loop (or the whole item) to the `todo-item` component. +## @Input\(\) + +We want to display the title of each item from within the `todo-item` component. We need to pass the title of the current item in the loop \(or the whole item\) to the `todo-item` component. Again, Angular makes it really easy for us, by providing us the `Input` decorator. Inside the newly generated `TodoItemComponent` class in `todo-item.component.ts` add the line: -```ts + +{% code-tabs %} +{% code-tabs-item, title="src/app/todo-item/todo-item.component.ts" %} +```typescript @Input() itemTitle: string; ``` -It tells the component to expect an input of type string and to assign it to the class member called `itemTitle`. Make sure that `Input` is added to the import statement in the first line in the file. Now we can use it inside the `todo-item` template with interpolation: `{{ itemTitle }}` +{% endcode-tabs-item %} +{% endcode-tabs %} -The component should look like this now: +It tells the component to expect an input of type string and to assign it to the class member called `itemTitle`. Make sure that `Input` is added to the import statement in the first line in the file. Now we can use it inside the `todo-item` template with interpolation: `{{ itemTitle }}` -```ts -// src/app/todo-item/todo-item.component.ts +The component should look like this now: -import { Component, OnInit } from '@angular/core'; +{% code-tabs %} +{% code-tabs-item, title="src/app/todo-item/todo-item.component.ts" %} +```typescript +import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'app-todo-item', @@ -59,39 +68,66 @@ export class TodoItemComponent implements OnInit { } ``` +{% endcode-tabs-item %} +{% endcode-tabs %} + +Now we need to pass a string, which is the item's title, where we use the component. Go back to `app-root` component and pass the item title to the `todo-item`: -Now we need to pass a string, which is the item's title, where we use the component. Go back to `appComponent` and pass the item title to the `todo-item`: -```html +{% code-tabs %} +{% code-tabs-item, title="src/app/app.component.ts" %} +```markup
    • - +
    ``` +{% endcode-tabs-item %} +{% endcode-tabs %} The `itemTitle` here in square brackets is the same as declared as the component's `@Input`. -We use property binding on an element we created ourselves! And now we can actually see and understand that property binding binds to actual property of the component. +We use property binding on an element we created ourselves! And now we can actually see and understand that property binding binds to actual property of the component. ## Passing the whole item + We will refactor our code a bit so we can easily implement more functionality in the `todo-item` component, for example editing and removing the item. Instead of passing just the title to the component, we will pass the whole item, and let the component extract the title where needed. -In `itemComponent` change the interpolation in the template to: -```html -{{ todoItem.title }} +In `todo-item.component.ts` change the interpolation in the template to: + +{% code-tabs %} +{% code-tabs-item, title="src/app/todo-item/todo-item.component.ts" %} +```typescript +template: ` + {{ todoItem.title }} +`, ``` -Rename the Input member and change its type: -```ts +{% endcode-tabs-item %} +{% endcode-tabs %} + +Rename the Input member and change its type: + +{% code-tabs %} +{% code-tabs-item, title="src/app/todo-item/todo-item.component.ts" %} +```typescript @Input() todoItem: any; ``` +{% endcode-tabs-item %} +{% endcode-tabs %} + +Now, in `app.component.ts` , in the component template, rename the bound property and pass the whole item \(remove the `.title`\): -Now pass the whole item to the renamed property in `appComponent` (remove the `.title`): -```html +{% code-tabs %} +{% code-tabs-item, title="src/app/app.component.ts" %} +```markup
    • - +
    ``` +{% endcode-tabs-item %} +{% endcode-tabs %} + +We now have a list of components, so each component received its data from the loop in the parent component. Next we'll see how this list can be dynamic. -We now have a list of components, so each component received its data from the loop in the parent component. Now we'll see how this list can be dynamic. diff --git a/property_binding.md b/property-binding.md similarity index 82% rename from property_binding.md rename to property-binding.md index 05ba250..89b49d3 100644 --- a/property_binding.md +++ b/property-binding.md @@ -6,7 +6,7 @@ Let's add an HTML input element and make its control text reflect the value of t We'll revert the component to its state before our experiments with its methods: -```ts +```typescript // src/app/input-button-unit/input-button-unit.component.ts import { Component, OnInit } from '@angular/core'; @@ -32,7 +32,7 @@ export class InputButtonUnitComponent implements OnInit { Let's add an input element and a button to the template: -```html +```markup // src/app/input-button-unit/input-button-unit.component.ts template: ` @@ -48,37 +48,39 @@ What if we want to show the title value inside the HTML input control itself? Every HTML `input` element has a property called `value`, which holds the string that is displayed inside the `input` box. In HTML we can pass a string directly to the element's `value` attribute: -```html +```markup ``` But we loose the dynamic binding between the properties in the controller to the template. -Angular lets us bind to **element properties** (not to be confused with class properties) to the template easily and conveniently. **We surround the wanted property with square brackets and pass it the class member**: +Angular lets us bind to **element properties** \(not to be confused with class properties\) to the template easily and conveniently. **We surround the wanted property with square brackets and pass it the class member**: -```html +```markup ``` Try this out and see the result in the browser! ## Binding to Methods + The expressions that we can bind to in the template are not limited to class properties. They can be a method call or almost any other valid JavaScript expression. -![lab-icon](/assets/lab.jpg) **Playground**: For example, let's bind the input value to a method call that returns a value. -First, let's add the method `generateTitle()` anywhere inside the class, but not inside any of its methods. +![lab-icon](.gitbook/assets/lab%20%281%29.jpg) + + **Playground**: For example, let's bind the input value to a method call that returns a value. First, let's add the method `generateTitle()` anywhere inside the class, but not inside any of its methods. -```ts +```typescript generateTitle(): string { return 'This title was generated by a method.'; } - ``` -Replace one or both of the bindings of the title in the template with the method's call (don't forget the parenthesis!): -```html +Replace one or both of the bindings of the title in the template with the method's call \(don't forget the parenthesis!\): + +```markup - + {{ generateTitle() }} ``` @@ -86,9 +88,11 @@ Replace one or both of the bindings of the title in the template with the method Angular has a very efficient change detection mechanism. It looks for bindings in the components' templates, and then updates the value each time the bound expression is changed. -![lab-icon](/assets/lab.jpg) **Playground**: To show this, let's change the value of the title after a few seconds and see what happens. Call the `setTimeout` function inside `ngOnInit`: +![lab-icon](.gitbook/assets/lab.jpg) + + **Playground**: To show this, let's change the value of the title after a few seconds and see what happens. Call the `setTimeout` function inside `ngOnInit`: -```ts +```typescript ngOnInit() { setTimeout(() => { this.title = 'This is not the title you are looking for'; @@ -96,8 +100,7 @@ ngOnInit() { } ``` -`setTimeout` is a JavaScript function. Its first parameter is what we want to happen - a function of our choice. The second parameter is how much we want to delay it, in milliseconds. In this example, we pass an inline anonymous function which sets the value of `this.title`. For this we use one of JavaScript's new features (ES6) **arrow function**. - +`setTimeout` is a JavaScript function. Its first parameter is what we want to happen - a function of our choice. The second parameter is how much we want to delay it, in milliseconds. In this example, we pass an inline anonymous function which sets the value of `this.title`. For this we use one of JavaScript's new features \(ES6\) **arrow function**. So for now, we have our input control show the title of our todo in it. We now want to make the input change the value of the title back by entering value in it and pressing enter. How to do that? Let's go to the next chapter and find out... @@ -116,7 +119,7 @@ inputElement.value = this.title; In JavaScript, we find the input element in the DOM by its id, and then set its `value` property to the value of the title variable. We need to add the id to the `input` element then: -```html +```markup ``` @@ -125,4 +128,3 @@ Excellent. However, **this is highly discouraged in Angular. You should never access the DOM directly!** That's because you can assign different renderers to Angular and run the application on different platforms. They may be mobile, desktop, or even a robot. And they will not have a `document` object from which you can manipulate the result! - diff --git a/refactor_app_component.md b/refactor-app-component.md similarity index 98% rename from refactor_app_component.md rename to refactor-app-component.md index ff35b83..95f4a40 100644 --- a/refactor_app_component.md +++ b/refactor-app-component.md @@ -5,10 +5,11 @@ We're going to perform a small refactoring. The app-root shouldn’t have such l * Create a new component called `list-manager`: `ng g c list-manager -it` + * Move all the code from `appComponent` to `listManager` * Call the new component from the `appComponent` template: -``` +```text ` ` diff --git a/remove-item.md b/remove-item.md new file mode 100644 index 0000000..4807f17 --- /dev/null +++ b/remove-item.md @@ -0,0 +1,66 @@ +# Remove item + +The user should be able to remove any item, whether it's still active or completed. Revoving an item will be done by clicking a button, aptly named "remove". In this tutorial, we'll learn how to add this functionality to our project. + +## File: item.component.ts + +First, we need to add the button to the item, so we'll work on the file _item.component.ts_. + +\(a\) Add a **\(click\)** event to the **remove** button in the item template: + +```text + +``` + +\(b\) Add a new output to the ItemComponent class, which will be emitted to the list manager when a user pressed the remove button for a specific item: + +```text +@Output() remove:EventEmitter = new EventEmitter(); +``` + +Make sure that we import both EventEmitter and Output in our class: + +```text +import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core'; +``` + +\(c\) Add a function to the ItemComponent class that will actually emit the event. This function will be called when the user clicks the **remove** button: + +```text +removeItem() { + this.remove.emit(this.todoItem); +} +``` + +## File: list-manager.component.ts + +Now that each todo item can emit its own removal, let's make sure that the list manager actually removes that same item from the list. For that, we'll work on the file _list-manager.component.ts_. + +\(a\) We need to respond to **remove** event - let's add it to the template, inside the `` tag: + +```text +(remove)="removeItem($event)" +``` + +\(b\) Now we just need to add the function _removeItem\(\)_ to the ListManagerComponent class: + +```text +removeItem(item) { + this.todoList = this.todoListService.removeItem(item); +} +``` + +## File: todo-list.service.ts + +Removing the item is handled in the service - open _todo-list.service.ts_ and add a function called removeItem\(\) to the TodoListService class: + +```text +removeItem(item) { + return this.storage.destroy(item); +} +``` + +This function calls the destroy\(\) method we already created in todo-list-storage.service.ts earlier. + diff --git a/remove_item.md b/remove_item.md deleted file mode 100644 index 4549d0b..0000000 --- a/remove_item.md +++ /dev/null @@ -1,57 +0,0 @@ -# Remove item - -The user should be able to remove any item, whether it's still active or completed. Revoving an item will be done by clicking a button, aptly named "remove". In this tutorial, we'll learn how to add this functionality to our project. - -### File: item.component.ts -First, we need to add the button to the item, so we'll work on the file *item.component.ts*. - -(a) Add a **(click)** event to the **remove** button in the item template: -``` - -``` - -(b) Add a new output to the ItemComponent class, which will be emitted to the list manager when a user pressed the remove button for a specific item: -``` -@Output() remove:EventEmitter = new EventEmitter(); -``` - -Make sure that we import both EventEmitter and Output in our class: -``` -import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core'; -``` -(c) Add a function to the ItemComponent class that will actually emit the event. This function will be called when the user clicks the **remove** button: -``` -removeItem() { - this.remove.emit(this.todoItem); -} -``` - -### File: list-manager.component.ts - -Now that each todo item can emit its own removal, let's make sure that the list manager actually removes that same item from the list. For that, we'll work on the file *list-manager.component.ts*. - -(a) We need to respond to **remove** event - let's add it to the template, inside the `` tag: -``` -(remove)="removeItem($event)" -``` - -(b) Now we just need to add the function *removeItem()* to the ListManagerComponent class: -``` -removeItem(item) { - this.todoList = this.todoListService.removeItem(item); -} -``` - -### File: todo-list.service.ts - -Removing the item is handled in the service - open *todo-list.service.ts* and add a function called removeItem() to the TodoListService class: - -``` -removeItem(item) { - return this.storage.destroy(item); -} -``` - -This function calls the destroy() method we already created in todo-list-storage.service.ts earlier. diff --git a/service.md b/service.md index 68675a4..09511d1 100644 --- a/service.md +++ b/service.md @@ -1,21 +1,22 @@ # Service -What and why ------------- +## What and why + Services are JavaScript functions that are responsible for doing a specific task only. Angular services are injected using Dependency Injection mechanism and include the value, function or feature which is required by the application. In our ToDo app, we will need a service to save all the tasks and to use it by injecting it into the components. -Create ------------- +## Create + In order to create a new service by **angular-cli**, we need to type this command on the root folder: - ng g s todoList +```text +ng g s todoList +``` This command will generate the service and put it under src/app/todo-list.service.ts -Provide in ngModule ------------- -Now, to start using the service, we first need to provide it in the @NgModule component. -In /src/app/app.module.ts , add an import code: +## Provide in ngModule + +Now, to start using the service, we first need to provide it in the @NgModule component. In /src/app/app.module.ts , add an import code: ```javascript import { TodoListService } from './todo-list.service'; @@ -41,8 +42,8 @@ And now add the service to the "providers" array, that the ngModule component wi That will allow us to create the service instance and to use it in any place of our app. -Move list from component to service ------------- +## Move list from component to service + We now need to move the todoList array from the component to our new service. The service will now have: ```javascript @@ -56,8 +57,8 @@ private todoList = [ ]; ``` -Create method on service to return the list ------------- +## Create method on service to return the list + Now go to the generated service file, found in src/app/todo-list.service.ts , and add a "getTodoList" function that will return the todoList array. The service will look like this: ```javascript @@ -84,12 +85,12 @@ export class TodoListService { } ``` -Inject to list-manager component and use the service ------------- +## Inject to list-manager component and use the service + After creating the service instance, we can inject it to our list-manager component. Go to /src/app/list-manager/list-manager.component.ts file and add the folllowing import code: ```javascript -import { TodoListService } from '../todo-list.service'; +import { TodoListService } from '../todo-list.service'; ``` And just use it in ListManagerComponent class: Remove the todoList array but keep the todoList member and change the constructor to be: diff --git a/the_list.md b/the-to-do-list.md similarity index 93% rename from the_list.md rename to the-to-do-list.md index 92edce7..f83bd54 100644 --- a/the_list.md +++ b/the-to-do-list.md @@ -2,7 +2,7 @@ Now, you are going to add the todo-list itself to the component `app-root`. Open the file `src/app/app.component.ts`. Add the list of items inside the `AppComponent` class as an array of objects for each item. At this stage each item object will contains only a title: -```ts +```typescript //src/app/app.component.ts export class AppComponent { @@ -19,11 +19,11 @@ todoList = [ > Putting info \(resources\) right inside your code is called hardcoding and considered an especially bad practice. Eventually we'll get the list from an outer resource, but even if not it's best to mock data in their own files. But let's advance step-by-step, so defining items this way is okay for now. -Now, you have to tell the browser to display those items. For this, you will use the **Angular built-in directive, `*ngFor`**. It works as an enhanced loop. `*` is a semantic though necessary notation which causes Angular to use the current element as template when rendering the list. +Now, you have to tell the browser to display those items. For this, you will use the **Angular built-in directive, **`*ngFor`. It works as an enhanced loop. `*` is a semantic though necessary notation which causes Angular to use the current element as template when rendering the list. Insert the loop right after ``, this way: -```html +```markup // src/app/app.component.ts template: ` @@ -41,18 +41,19 @@ template: ` `, ``` -This means "go over all items of todoList array defined in the class, and print out a list which contains the items' titles". While looping over the `todoList`, each item is assigned to the template variable `item`, and we can use this variable inside the element in which we define it (in this case the `li` element) and its children. +This means "go over all items of todoList array defined in the class, and print out a list which contains the items' titles". While looping over the `todoList`, each item is assigned to the template variable `item`, and we can use this variable inside the element in which we define it \(in this case the `li` element\) and its children. -### Angular directives +## Angular directives Directives are pieces of logic \(written as classes\) that can be attached to elements and components. They are used to change the display or the behavior of the element. Angular comes with some built-in directives. As we saw, the `ngFor` directive modifies the template in run-time by repeating the element it's called on and its content. Another directive for example is `ngIf`, which receives a Boolean expression. Only if the expression is true Angular renders the element and its content. It also needs the `*` prefix because it uses the target element as a template, similarly to the `*ngFor` directive. For example: -```html +```markup

    Welcome!

    ``` In this example, `userLoggedIn` should be a member of the component, and have a true or false value. If it's true, the element will be displayed. If false, the element will not exist on the DOM. There are other directives in Angular which are not structural \(and are used without the `*`\). For example ngStyle and ngClass, with which you can dynamically apply style and classes to the element. +