Book Image

Angular Projects - Third Edition

By : Aristeidis Bampakos
5 (2)
Book Image

Angular Projects - Third Edition

5 (2)
By: Aristeidis Bampakos

Overview of this book

Angular Projects isn't like other books on Angular – this is a project-based guide that helps budding Angular developers get hands-on experience while developing cutting-edge applications. In this updated third edition, you’ll master the essential features of the framework by creating ten different real-world web applications. Each application will demonstrate how to integrate Angular with a different library and tool, giving you a 360-degree view of what the Angular ecosystem makes possible. Updated to the newest version of Angular, the book has been revamped to keep up with the latest technologies. You’ll work on a PWA weather application, a mobile photo geotagging application, a component UI library, and other exciting projects. In doing so, you’ll implement popular technologies such as Angular Router, Scully, Electron, Angular service workers, Jamstack, NgRx, and more. By the end of this book, you will have the skills you need to build Angular apps using a variety of different technologies according to your or your client’s needs.
Table of Contents (13 chapters)
11
Other Books You May Enjoy
12
Index

Displaying blog posts on the home page

We would like our users to see the list of available blog posts as soon as they land on our blog website. According to the default route path that we have defined, ArticlesComponent is the landing page of our blog. Scully provides ScullyRoutesService, an Angular service that we can use in our components to get information about the routes that it will create according to the blog posts. Let’s put this service into action on our landing page:

  1. Open the articles.component.ts file and modify the import statements as follows:
    import { Component, OnInit } from '@angular/core';
    import { ScullyRoute, ScullyRoutesService } from '@scullyio/ng-lib';
    import { Observable, map } from 'rxjs';
    
  2. Add the OnInit interface to the list of implemented interfaces of the ArticlesComponent class:
    export class ArticlesComponent implements OnInit {
    }
    
  3. Inject ScullyRoutesService in the constructor of the ArticlesComponent class:
    constructor(private scullyService: ScullyRoutesService) { }
    
  4. Create the following component property:
    posts$: Observable<ScullyRoute[]> | undefined;
    
  5. Implement the ngOnInit method:
    ngOnInit(): void {
      this.posts$ = this.scullyService.available$.pipe(
        map(posts => posts.filter(post => post.title))
      );
    }
    
  6. Open the articles.component.html file and add the following HTML code:
    <div class="list-group mt-3">
      <a *ngFor="let post of posts$ | async"
        [routerLink]="post.route" class="list-group-item
          list-group-item-action">
        <div class="d-flex w-100 justify-content-between">
          <h5 class="mb-1">{{post.title}}</h5>
        </div>
        <p class="mb-1">{{post['description']}}</p>
      </a>
    </div>
    

There are many Angular techniques involved in the previous steps, so let’s break them down piece by piece.

When we want to use an Angular service in a component, we just need to ask for it from the Angular framework. How? By adding it as a property in the constructor of the component. The component does not need to know anything about how the service is implemented.

The ngOnInit method is part of the OnInit interface, which is implemented by our component. It is called by the Angular framework when a component is initialized and provides us with a hook to add custom logic to be executed.

Angular services that provide initialization logic to a component should be called inside the ngOnInit method and not in the constructor because it is easier to provide mocks about those services when unit testing the component.

The available$ property of ScullyRoutesService is called an observable and returns all the available routes that were generated from Scully when we subscribe to it. To avoid displaying routes other than those related to blog posts, such as the contact route, we filter out the results from the available$ property.

In the component template, we use the *ngFor Angular built-in directive and the async pipe to subscribe to the posts$ observable inside HTML. We can then access each item using the post template reference variable and use interpolation to display title and description.

Finally, we add a routerLink directive to each anchor element to navigate to the respective blog post when clicked. Notice that routerLink is surrounded by []. The [] syntax is called property binding, and we use it when we want to bind the property of an HTML element to a variable. In our case, we bind the routerLink directive to the route property of the post variable.

Now that we have finally completed all the pieces of the puzzle, we can see our blog website in action:

  1. Run the build command of the Angular CLI to build our Angular application:
    ng build
    
  2. Execute the following command to build Scully and generate our blog routes:
    npx scully --project my-blog
    

    The preceding command will create a scully-routes.json file inside the src\assets folder. It contains the routes of our Angular application and is needed by the Scully runtime.

    Running the Scully executable for the first time will prompt you to collect anonymous errors to improve its services.

  1. Run the following command to serve our blog:
    npx scully serve --project my-blog
    

The preceding command will start two web servers: one that contains the static prerendered version of our website built using Scully and another that is the Angular live version of our application:

Figure 2.5 – Serving our application

If we open our browser and navigate to http://localhost:1668, we will not see any blog posts. A blog post created with Scully is not returned in the available$ property of ScullyRoutesService unless we publish it. To publish a blog post, we do the following:

  1. Navigate to the mdfiles folder that Scully created and open the only .md file that you will find. The name and contents may vary for your file because it is based on the date Scully created it:
    ---
    title: 2023-06-22-posts
    description: 'blog description'
    published: false
    slugs:
        - ___UNPUBLISHED___lj738su6_7mqWyfNdmNCwovaCCi2tZItsDKMPJGcG
    ---
    # 2023-06-22-posts
    

    Scully has defined a set of properties between the closing and ending --- lines at the top of the file representing metadata about the blog post. You can also add your own as key-value pairs.

  1. Delete the slugs property and set the published property to true:
    ---
    title: 2023-06-22-posts
    description: 'blog description'
    published: true
    ---
    # 2023-06-22-posts
    
  2. Run the following command to force Scully to regenerate the routes of our application:
    npx scully --project my-blog
    

    We need to execute the previous command every time we make a change in our blog-related files.

  1. Execute the npx scully serve --project my-blog command and navigate to preview the generated website.

We can now see one blog post, the default one that was created when we installed Scully. Let’s create another one:

  1. Run the following generate command of the Angular CLI:
    ng generate @scullyio/init:post --name="Angular and Scully"
    

    In the preceding command, we use the @scullyio/init:post schematic, passing the name of the post that we want to create as an option.

  1. Set the target folder for the new blog post to mdfiles:
    What's the target folder for this post? (blog)
    
  2. Scully will create a Markdown file named angular-and-scully.md inside the specified folder. Open that file and update its content to be the same as the following:
    ---
    title: 'Angular and Scully'
    description: 'How to build a blog with Angular and Scully'
    published: true
    ---
    # Angular and Scully
    Angular is a robust JavaScript framework that we can use to build excellent and performant web applications.
    Scully is a popular static website generator that empowers the Angular framework with Jamstack characteristics.
    You can find more about them in the following links:
    - https://angular.io
    - https://scully.io
    - https://www.jamstack.org
    
  3. Run npx scully --project my-blog to create a route for the newly created blog post. Scully will also update the scully-routes.json file with the new route.

If we preview our application now, it should look like the following:

Εικόνα που περιέχει κείμενο, στιγμιότυπο οθόνης, γραμματοσειρά, γραμμή  Περιγραφή που δημιουργήθηκε αυτόματα

Figure 2.6 – List of blog posts

If we click on one of the blog items, we will navigate to the selected blog post. The content that is currently shown on the screen is a prerendered version of the blog post route:

Εικόνα που περιέχει κείμενο, στιγμιότυπο οθόνης, γραμματοσειρά  Περιγραφή που δημιουργήθηκε αυτόματα

Figure 2.7 – Blog post details

To verify that, navigate to the dist folder of your Angular project, where you will find two folders:

  • my-blog: This contains the Angular live version of our application. When we execute the ng build Angular CLI command, it builds our application and outputs bundle files in this folder.
  • static: This contains a prerendered version of our Angular application generated from Scully when we run the npx scully --project my-blog command.

If we navigate to the static folder, we will see that Scully has created one folder for each route of our Angular application. Each folder contains an index.html file, which represents the component that is activated from that route.

The contents of the index.html file are auto-generated by Scully, and behave as if we run our application live and navigate to that component.

Now you can take your Angular application, upload it to the CDN or web server of your choice, and you will have your blog ready in no time! All you will have to do then will be to exercise your writing skills to create excellent blog content.