In the previous article [Understanding Angular 7] The first settings , I and you have learned about the basic settings to be able to run the Angular project. In this article, let’s try to write simple code together.
Running the application
Making a Component
One of the great ideas behind Angular is the idea of components
. In the Angular application, we write HTML tags to represent and help the application interact with the user. But browsers only understand a limited set of built-in tags such as <select>
, <form>
or <video>
.
What if we teach the browser a new tag ?. And what happens if we want the <weather>
tag to display <weather>
information? Or if we want to create a <login>
tag to display the login panel, what should we do?
And this is the basic idea behind components
: that is, teach the browser new tags, and customize their functionality.
If you have an AngularJS 1.X background, you can think of
components
as a new version of directives
Come on, let me create the first component. Once created we can use it in our HTML document, by calling the app-hello-world
tag:
<app-hello-world></app-hello-world>
To create a new component using the Angular CLI, we will use the generate command.
For example, to create a hello-world
component, we need to run the following command:
1 2 3 4 5 6 7 8 | $ ng generate component hello-world CREATE src/app/hello-world/hello-world.component.css (0 bytes) CREATE src/app/hello-world/hello-world.component.html (30 bytes) CREATE src/app/hello-world/hello-world.component.spec.ts (657 bytes) CREATE src/app/hello-world/hello-world.component.ts (288 bytes) UPDATE src/app/app.module.ts (414 bytes) |
So how is a new Component defined? A basic component has 2 components:
- A Component decorator
- A Component defines the class
First, let’s see the component code below. Open TypeScript file hello-world.component.ts
src / app / hello-world / hello-world.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import {Component, OnInit} from '@angular/core'; @Component({ selector: 'app-hello-world', templateUrl: './hello-world.component.html', styleUrls: ['./hello-world.component.css'] }) export class HelloWorldComponent implements OnInit { constructor() { } ngOnInit() { } } |
Looking at the above code seems quite clumsy right? Don’t worry so much, we’ll go look at it step by step.
Notice that the tail of the TypeScript file above is
.ts
rather than.js
, the problem is that our browser doesn’t know how to interpret the TypeScript file. And to solve that problem, theng serve
command will automatically compile the.ts
file to.js
.
Importing Dependencies
Statements import
will define the modules that we want to write the code. Here, we are importing 2 things: Component
and OnInit
.
We will import Component
from the "@angular/core"
module. And "@angular/core"
will tell our program where to find the dependencies we want. And in this case, we are telling the compiler, "@angular/core"
let’s define and export two JavaScript / TypeScript objects: Component
and OnInit
And we also import OnInit
from the same module as above. This we will learn later, but in short, OnInit
will help us run the code when initializing the Component, but for now, do not care about it yet.
Note that the format of the import command is: import { thứ mong muốn } từ đâu đó
.
In the { thứ mong muốn }
we are using is called destructuring
. Destructuring is a feature provided by ES6 and TypeScript. We will talk more about it in later sections.
The idea of import
is quite similar with import
in Java and require
in Ruby: We pulled it from the dependencies another module and make it ready for use in this file.
Component Decorators
After importing the dependencies, we continue to declare Component:
src / app / hello-world / hello-world.component.ts
1 2 3 4 5 6 | @Component({ selector: 'app-hello-world', templateUrl: './hello-world.component.html', styleUrls: ['./hello-world.component.css'] }) |
If you’re new to TypeScript, the syntax of this next statement may seem a bit strange:
1 2 3 4 | @Component({ //... }) |
This is called decorators
.
In simple terms, decorators
as metadata are added to your code. When using @Component
in HelloWorld
class, it is that we are treating HelloWorld
as a component.
If you want to be able to use this component by using the <app-hello-world>
tag, then you need to configure @Component
and specify the selector
as app-hello-world
.
1 2 3 4 5 | @Component({ selector: 'app-hello-world' // ... more here }) |
The syntax of Angular component selectors is similar to that of CSS selectors (however, Angular components also have some special syntax for selectors, we will learn in the next section). For now, let’s just understand that the selector will define a new tag.
The selector
attribute specifies which DOM element
this component will use. In this case, any <app-hello-world></app-hello-world>
that appear in the template are compiled by the HelloWorldComponent class and receive any attached functionality.
Adding a template with templateUrl
In the component, we specify templateUrl
as ./hello-world.component.html
. This means we will load the template from hello-world.component.html
file in the same directory as the component. Take a look at the file below:
src / app / hello-world / hello-world.component.html
1 2 3 4 | <p> hello-world works! </p> |
Here, we have defined a tag p
with a basic text. When Angular loads this component, it will read from this file and use it as a component template.
Adding a template
We can define the template in two ways, either using the template
key in @Component
or specifying templateUrl
. Below, we will add the template
key to @Component
:
1 2 3 4 5 6 7 8 9 | @Component({ selector: 'app-hello-world' template: ` <p> hello-world works inline! </p> ` }) |
Here we are defining a character string of the template using a backtick ( ...
). This is a great new feature of ES6 that allows us to write a string of characters on multiple lines. It allows us to easily place the template
in this file.
The question is, should I write the template directly in this code file? The answer is: it depends on the case. Until now, people still recommend that code and template should be separated. This may be easy for some teams, but for some projects, it will generate more resources because of having to switch between lots of files.
For my personal opinion, if the template is shorter than a page, I prefer to write the template and code together (that is, write in the same
.ts
file). When both logic and view code are written together, it is easy to understand the interaction between them.The biggest drawback of writing between code and view is that many editors do not support displaying the code template in
.ts
files. Hopefully, there will be more editors that support formatting html code in the template.
Adding CSS Styles with styleUrls
Notice the styleUrls
key
styleUrls: ['./hello-world.component.css']
This means, we will use the CSS in the file hello-world.component.css
for this component. Angular uses a concept called “style-encapsulation”, which means that styles that are assigned to a specific component apply only to that component. . We will talk more about this in a later section.
Currently, we don’t use any component-local styles, so you can leave that file as it is.
You may have noticed that this key is different from the
template
, which accepts an array of arguments. This is because we can load multiple stylesheets for a single component
Loading Our Component
We have our first component, so how do we load it into our page?
When we revisit the application in the browser, we didn’t see any changes. The reason is because we have created that component, but not yet used it.
So after this, we will add the component tag to the template that has been rendered. Open file: src/app/app.component.html
Remember we have configured HelloWorldComponent
with the app-hello-world
selector, so we can use the <app-hello-world></app-hello-world>
tag in the template. Now add the <app-hello-world>
app.component.html
to the app.component.html
file.
1 2 3 4 5 | <h1> {{title}} <app-hello-world></app-hello-world> </h1> |
After refreshing the browser, it will look like this:
Adding Data to the Component
Currently, our component is rendering a static template, so that component is not very interesting.
Imagine we have an app showing list users with their names. Before rendering the list of uers, we will render a user first. Now, create a new component to show the user’s name.
We use the command ng generate
to create a new component:
ng generate component user-item
Remember, to see the component we have just created, we need to add it to the template. Add the app-user-item
tag to the app.component.html
file as follows:
1 2 3 4 5 6 7 | <h1> {{title}} <app-hello-world></app-hello-world> <app-user-item></app-user-item> </h1> |
After refreshing the page, you will see text user-item works!
appears on the page.
And here, we will let UserItemComponent
display the name of a specific user. Now create a new property
called name
. Once we have the property name
, we can reuse this component to many different users. (keep the same logic and style).
We will create a local name
variable into the UserItemComponent
as shown below:
src / app / user-item / user-item.component.ts
1 2 3 4 5 6 7 8 9 10 11 | export class UserItemComponent implements OnInit { name: string; // added name property constructor() { this.name = 'Felipe'; // set the name } ngOnInit() { } } |
Note, we have just changed 2 things:
1. name
Property
In the UserItemComponent Class, we have added a new property
. This is a new syntax compared to ES5 JavaScript. When we write name: string
, it means that we are declaring property name
type string
.
By setting this variable into a string
, the compiler will ensure the variable name
is a string, and will throw error if we assign it a value number
such. This syntax is also the way TypeScript defines instance properties. By setting name: string
like this, we are providing UserItemComponent with a property name
.
2. Constructor
In the UserItemComponent
class we have defined a constructor
, which is a function that is called when we create a new instance of the class. In the constructor
we can assign values to the name
property by writing this.name
.
Specifically when we write:
src / app / user-item / user-item.component.ts
1 2 3 4 | constructor() { this.name = 'Felipe'; // set the name } |
We are saying that whenever a new UserItemComponent is created, set the value of name
to ‘Felipe’.
Rendering The Template
When we have a property in the component, we can display that value in the template by using two braces {{}}.
For example, we write the following:
src / app / user-item / user-item.component.html
1 2 3 4 | <p> Hello {{name}} </p> |
Note that we have just added a new syntax, {{name}}. These brackets are called template tags
(or sometimes mustache tags
).
Anything inside the template tags
will be expanded as an expression. Here, the template
is linked to the Component so the name
variable will be expanded to the value of this.name
, for example ‘Felipe’.
Try It Out
After making the above changes, we reload the page, the page will display as Hello Felipe
Over. Invite you to refer to the next article
Source: https://www.ng-book.com/2/