Building applications with Angular 7 (Part 2)

Tram Ho

Rendering Multiple Rows

In the last article, we made an additional article on the page, can perform upVote, downVote. However, there is no way to add a new post unless we paste the <app-article> tag. However, if you do that, all the posts will have the same content and that is really not interesting. In this article, we will continue to complete the other functions of this Reddit application.

Creating an Article class

A good habit of writing Angular code is to always try to isolate / isolate the data structure we use from component code. To do this, we will create a data structure that represents a single article . We will add a new file, article.model.ts to define Article class.

angular-reddit-app / src / app / article / article.model.ts

Here, we have created a new class that represents a Article . Note that this is a normal class, not an Angular component. In the Model-View-Controller pattern, this class is Model .
Each article has a tile , a link and a total value that displays the total number of votes . When creating a new article we need the title and link . And the votes parameter is optional (so at the end of the variable name, we add the question mark?) And the default value will be 0.
We will now update the code in ArticleComponent so we can use the newly created Article class. Instead of storing properties directly in ArticleComponent we will store them in Article class instance.
First, import Article class.

angular-reddit-app / src / app / article / article.component.ts
import { Article } from "./article.model";

Using Article class insance angular-reddit-app / src / app / article / article.component.ts

Notice some things we changed: instead of saving the title , link , and votes directly into the component, we store a reference to the article .
Similarly, we will not increase votes directly on the component anymore, but increase the value of votes through the article .
Besides, we also need to update the code in the view to be able to get values ​​from the article , the previous example we wrote is {{votes}}, now it will be revised to {{ article.votes }} , and do the same for the title and link .

angular-reddit-app / src / app / article / article.component.html

Perform reloading the browser and everything is working normally.
At first glance it seems that the code is better, but there are still incomplete points, which makes the voteUp and voteDown methods are breaking Article ‘s packaging by directly changing the inner properties of the article.

voteUp and voteDown violated the Law of Demeter principle. That principle states that one object should minimize direct access to the properties of another object.

The problem here is that ArticleComponent knows too much about Article class. To fix that, we will add two methods, voteUp and voteDown, into Article class. (We will also add a domain function, and I’ll briefly explain this function)
angular-reddit-app / src / app / article / article.model.ts

Besides, we also need to edit ArticleComponent to be able to call these functions:

angular-reddit-app / src / app / article / article.component.ts

Why do we need the voteUp function in both the model and component?
The reason we need to have voteUp() and voteDown() in both classes is that each function will perform a slightly different job. The idea is that voteUp() on ArticleComponent will relate to component view . Meanwhile Article model voteUp() will define the behavior happening in the model .
That is, it allows the Article class to encapsulate the functionality that will occur in the model when voting. In practical applications, the content within the Artical modal may be more complex. For example, you have to make an API request to the webserver, and you don’t need to have a specific model code in the component controller.
Similarly, in ArticleComponent we also return false . That’s a way not to pass the event, because this is the logic specific to the view so we should not allow the voteUp() function of Article model to know the type of API specific to the view. Article model should allow voting independently of the view.

After reloading the browser we found that the application still works the same as before, but our code is much clearer and simpler.

ArticleComponent at ArticleComponent we see that it has become very brief, because we have moved most of the logic of the component to the purpose model so that our component performs the minimum amount of work possible. Read more about MVC Fat Models, Skinny Controllers .

Storing Multiple Articles

Now we will write code to have a list of not many Articles. First, it will revise the AppComponent .
src / app / app.component.ts

Notice that in AppComponent there is this line:
articles: Article[];
At first, Article [] looks a bit strange. This line of code means that we declare articles as an array of Articles. There is another way of writing it is Array <Article>. This is similar in other languages ​​such as Java, C #, … This array contains only Article objects.
To access the Article class, we must first import it – this one we insert at the top. We enter data for this Array by writing this.articles in the constructor.
src / app / app.component.ts

Configuring the ArticleComponent with inputs

We now have a Article list, so how can we pass it into ArticleComponent ?
Again we will use Inputs . Last time our ArticleComponent class was defined as follows:
src / app / article / article.component.ts

The problem is that we have hard-coded a specific Article in the constructor. This makes the component not only lose packaging, but also cannot be reused.
What we want to do here is the configure Article we want to display. For example, we have two articles is article1 and article2 , we can re-use app-article component by passing an Article as a parameter to the component, as in the following:

Angular allows us to do this by using the Input decorator in the component’s property:

If there is a Article in a myArticle variable, we can pass it to ArticleComponent from view. Remember, we can pass a variable to the element by enclosing it with a pair of square brackets [variableName]:

Note the syntax here: We have named the input in brackets [article] , and the value of the attribute is what we want to pass into the input. Then this.article in ArticleComponent will be set to myArticle . We can think of myArticle as passed as a parameter to the component.

This is ArticleComponent after using @Input :
src / app / article / article.component.ts

Do not forget to import!
Notice that we have import Input class from @angular/core . We also imported Article model when we did with AppComponent earlier.

Rendering a List of Articles

Earlier, we had configured AppComponent to store an array of articles . And now we will configure AppComponent to gender out all the articles . To do that, instead of using an <app-article> tag, we will use the NgFor directive to loop through a list of articles and gender app-article for each item.
We will add it in the AppComponent @Component template , and it is right below the closing <form> tag.

Remember we gender gender a list of name using NgFor directive in the previous chapter? This Syntax also applies to gender of multiple components at once.
The syntax *ngFor="let article of articles" will loop over a list of articles and create a local article variable for each item in the list.
To specify article input in the component, we use the expression [inputName]="inputValue" . In this case, we are saying that we want to set the value of the local article variable for the article input with the ngFor command.

We have used the article variable many times in the previous code, to be more clear, change the temporary variable name in ngFor to foobar :

So here we have 3 variables:

  1. articles is an array of Articles defined in AppComponent .
  2. foobar is a single element of articles , defined in ngFor .
  3. article is the name of the field defined on ArticleComponent ‘s Input .

In a nutshell, ngFor will create a temporary foobar variable, and pass it to the app-article .
Reload the browser, you will see the articles are gender.

Adding New Articles

We need to edit the addArticle function so we can add new articles when the Submit link button is clicked.
src / app / app.component.ts

 

The above code will do the following:

  1. Create a new Article instance along with the submitted title and URL
  2. Add it to Articles array
  3. Delete the value of the input field

How to delete value of input field? Remember, title and link are HTMLInputElement objects . That means we can set their properties. When we change the value attribute, the input tag will change as well.

After adding the article to the input field and clicking the Submit Link button, we will see the newly added article.

Finishing Touches

Displaying the Article Domain

As a great suggestion, if we can display a hint text next to a link to show the domain the user will redirect until the link is clicked.
Add the domain method to classi Article :
src / app / article / article.model.ts

Call this function in the ArticleComponent template.

Conduct reloading the browser, the domain name of each URL will be displayed. (Note the URL must include http: //)

Re-sorting Based on Score

When clicking and performing a vote, we see that there is something wrong here: the articles not sorted based on the score . And what I want is to see that the item with the highest score will show first, and the item with the lower score will show below. We are saving articles in the array in the AppComponent class, but the array is not being sorted. A simple way to handle this problem, is to create a new method, sortedArticles in AppComponent :

ES6 Arrow Function
The above code used the function (=>) from ES6. Refer to the Arrow function
We are also using the built-in sort () function. Refer to the sort () method

In ngFor we will iterate over sortedArticles() (instead of iterating directly on articles )

Deployment

So we have finished the application, and we want it to run on the internet so it can be shared with friends.

Deployment and performance in products are the next topic that I will cover later on. At the moment, I want to introduce a basic, easy way to deploy applications to the internet.

Deploy is an act of pushing your code onto the server, which is accessible to others. In more detail, the idea we will do is:

  • Compile all TypeScript code into JavaScript code (which the browser can read)
  • Bundle (encapsulate) all JavaScript code in one or two files.
  • Then upload JavaScript, HTML, CSS and images to the server.

Basically, this Angular app is an HTML file that loads the JavaScript code. And we need to upload this code to a computer on the internet.
First, let’s build our Angular app.

Building Our App for Production

The Angular CLI tool – the one we used to generate the app in the beginning can be used to build the app in a single command.
In angular-reddit project, we type the following command:
ng build --prod
This will require ng tool build our application environment for production .
This command will run for a moment, and after it is finished, the dist folder will appear.

These files are the result of our complete application aggregation. Note that there is a long string in the middle of each file, as shown below:
main.395e7d51ca3415f1ee22.js
These characters are hash codes of the content. (For each computer, it may be different). When looking at each file, we can see some of the following files: icons, index.html, main.js, a polyfills.js, a vendor.js, and styles.css.
What we need to do next is to upload it all to the server.

Uploading to a Server

There are many ways to host your HTML and Javascript code. To demo, we have the easiest way is to use Now

If you don’t want to use Now , you can use any method you want. For example, you can host sites on Heroku, AWS S3, upload files to your own server via FTP … etc.
Importantly, the server can display all the files in the dist directory on the internet.

Installing now

We can install now by using npm :
npm install -g now
Or use yarn:
yarn global add now
And run the following command to deploy:

The now command will ask you a few questions (such as your email address), and you need to check your mail and click on the link in it.
After you confirm your account, now will upload your code, and will provide you with a URL so you can view your application.
Go to that URL, and view your app. If it works, send this URL and show it to your friends!
Congratulations! You have successfully built and deployed the first Angular application!

Full Code Listing

So we have learned a lot about Angular in seria creating this application. You can read through the previous articles to better understand.

Wrapping Up

Thus, we have completed the first Angular application, simple but quite interesting application, right ?!
We have learned a lot of things like: understanding data flow, making AJAX requests, built-in directives, routing, manipulating DOM … etc.
The main tasks for writing the Angular application, we have all done above:

  1. Split the app into components.
  2. Create the view
  3. Define models.
  4. Display models.
  5. Add interaction.

In the following articles, we will continue to explore other topics related to Angular.

Getting Help

If you have something to discuss, please comment below each article.

Source: https://www.ng-book.com/2/

Share the news now

Source : Viblo