Fullstack Wizard 4. Know when to call it quits. Angular modules, routes and components.
Girl programming

Fullstack Wizard 4. Know when to call it quits. Angular modules, routes and components.

By Alexandru-Balan | Pr0gram Failure | 2 Aug 2020


Previous episodes:

fstk.png

Before word

"Wait a minute. This is episode 4 and still no Vue guide. Where is my Vue guide?"

I know, I know. I promised you a Vue guide and then I postponed it and then again while I was rambling about front-end design and container orchestration with Docker. But it was fun, wasn't it? Well, today I'm officially announcing that the Vue guide will never come.

As my project, Instrumentality, which this series is all about, got bigger and bigger, Vue proved to be a very bad tool for managing it. Don't get me wrong, Vue was awesome for creating a small landing site, but at some point, I decided on integrating the landing site in the full application as a module.

The downside of it was that one was written with Vue and the other with Angular. Whatever people say about Angular being big and bloated, they are right. But it's for a good reason. The way everything is sorted into modules, components, directives, etc. is unmatched by any other JavaScript framework. Also having everything a modern web app needs, like HTTP clients, dependency injection, routing, guarding, and so on, baked into the framework itself gives it a feel of unity and you can develop solutions more cohesively.

The problem with Vue was that everything I'd want to do for a full application could only be achieved through the use of plugins. Some plugins are better than others and they usually bring their own set of extra dependencies. So instead of searching the web for the best plugins and trying to port the Angular part to Vue, I decided on going with the massive Angular framework and port the landing site.

instrumentalitynew.png

A quick update on Instrumentality

Alright, before getting into the main course which is about Angular and a few tips on how to use it, I'd like to give you some short updates about my project.

What is Instrumentality?

Instrumentality is a project I'm developing as my final thesis for university. It is an application that is meant to make developer recruitment an easier and more trustworthy process.

Problems with the current system:

  • People in recruitment don't know a thing about tech and wrongfully quantify experience in years.
  • Developers lie about their experience in order to get jobs because requirements are abnormally high.
  • Because they can't trust developers, companies use programming examinations with automated tests. Some of those tests are so bad that every little mistake means you don't get scored which might disqualify great developers for nothing.

Solutions Instrumentality is trying to implement:

  • In theory, this system will be used by companies to assign tasks to employees, like they already do with tools like Jira.
  • The tasks must have attached a maximum of three technologies that are required for completion.
  • When the task is completed, the developer receives a portion of a token with the same name as the technology. Let's say you complete a task that requires you to work with JavaScript, in the end, you'll be rewarded with 0.001 JS tokens.
  • Instrumentality uses a permissioned blockchain to create privacy between the developers and the companies while storing the information in a trustworthy way. This way companies can have a much better idea of someone's skills than trying to quantify their experience in years.

Where I am now?

Well, the following things are implemented:

  • Landing website
  • Hyperledger Iroha blockchain configured
  • Python API that bridges frontend HTTP requests to Iroha blockchain
  • Authentication on the chain for developers
  • Storing additional data on the blockchain like name, etc.
  • Docker containers for all components and orchestration of containers

Here is a little video of Instrumentality in action:

Angular -- quick project setup

Alright enough rambling, let's get to the fun part. Using Angular can seem rather difficult for new users to the massive amount of features that it puts at our disposal. However everything is very neatly organized so once you get the ropes of Angular, you'll be just fine.

To get Angular working you'll need to install Node.js and a package manager like npm or yarn which you can get by following the instructions on the first episode.

Next, to install Angular run:
sudo yarn global add @angular/cli

After installing it, you'll have a new program on your computer called ng which is accessible through the terminal:

Screenshot from 20200802 090204.png

To create a new project using this tool you just run: ng new awesome-project. Instead of awesome-project you can use any other name you like.

Angular will then ask you if you want to include a couple of features in your project by default like routing or CSS preprocessing:

Screenshot from 20200802 090729.png

Screenshot from 20200802 090852.png

I included routing and I opted for the LESS preprocessor. After choosing these two options I just let Angular work its magic.

For us to see the app in action in our browsers we can navigate to the folder containing our project, in my case I'd do cd awesome-project and then run ng serve -o. The -o option will open your browser automatically at the URL where your app is served which is usually localhost:4200.

Angular modules

Angular modules represent multiple parts of your app that are put together into a single cohesive unit. For example, my project has two modules right now. One is the landing website which also handles authentication and the other is the dashboard for developers.

Your application already has a module that every Angular app does. It's called the app module and can be found in src/app/app.module.ts.

Creating a new module for your Angular project is extremely easy. All you have to do is run ng generate module new-module --routing from the root of your project directory. Again, choose whatever name you like for the module instead of new-module.

The --routing option gives our module routing capacities so we can define links that show different components in our browser.

ngl.png

Angular components

Angular components are small elements in your app that show up in the browser. They have an HTML structure, a CSS style, and eventually some TypeScript logic.

Let's go ahead and create a new component that has the same name as our module. To do that we can just type the following command at our terminal: ng generate component new-module.

Now you can see that in your src/app/new-module folder there have been some new files created. One of them is an HTML file. Let's go ahead and open it in a code editor of your choice. I replaced the initial contents of that file with the following:

<section>
    <h1>This is the new-module component</h1>
</section>

Let's also add some style to our component by editing the .less file that's in the same folder:

section {
    height: 100vh;
    width: 100vw;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;

    h1 {
        font-weight: 900;
        font-size: calc(3em + (50 - 3) * ((100vh - 320px) / (3840 - 320)));
    }
}

Since we're editing Angular components let's also edit the app component. We must open the file called app.component.html in src/app. Delete all the content there except the <router-outlet> tag. Angular will replace that tag with a component when we access its route.

Let's place a minimal navbar in our app component:

<nav>
  <ul>
    <li><a [routerLink]="['new_module']">Go to new module</a></li>
  </ul>
</nav>

<router-outlet></router-outlet>

And we should also take care of the style:

nav {
    width: 100%;
    height: auto;
    display: flex;
    flex-direction: row;
    align-items: flex-start;

    ul {
        list-style: none;

        li a {
            text-decoration: none;
            font-size: calc(1em + (20 - 1) * ((100vw - 320px) / (3840 - 320)));
            color: blue;
            position: relative;
        }

        li a::before{
            position: absolute;
            content: "";
            background-color: blue;
            width: 50%;
            height: 2px;
            left: 25%;
            bottom: 0;
            visibility: hidden;
            transform: scaleX(0);
            transition: all .25s cubic-bezier(1,.25,0,.75);
        }
        
        li a:hover::before {
            transform: scaleX(1);
            visibility: visible;
        }
    }
}

That looks better and has a nice effect that triggers when we hover over the link.
Screenshot from 20200802 102348.png

Clicking the link, however, has no effect as we are yet to define the routes that make it possible for Angular to replace the <router-outlet> with an actual component.

Angular routes

Since we created our new-module component with the --routing option we have a file in our module's folder called new-module-routing.module.ts. In the routes list we can define our routes relative to the module. You'll find more about relative routes, later when we define the routes in our app module.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { NewModuleComponent } from "./new-module.component";

const routes: Routes = [
  {
    path: '',
    component: NewModuleComponent
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class NewModuleRoutingModule { }

Alright, let's focus now. We create a route with an empty path that uses our NewModuleComponent. When you access the route of a module, Angular will look in this collection and will try to load the route that fits your URL. For example if Module1 can be found at localhost:4200/mod1, Angular will load the empty route with path:' '. If you have other components in this module you'll have to specify unique paths for their routes so that a component, Component1, that has path: comp1 will be found at localhost:4200/mod1/comp1.

We should now turn our attention to the app routing module defined in the app-routing.module.ts file and define a route to our new module. Because we are cool and want our app to be performant we should lazy-load our components. What this means is that the new module will not be downloaded from the server and executed until you try to access it. This leads to a faster loading app for your users and reduced bandwidth.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
  { path: 'new_module', loadChildren: () => import('./new-module/new-module.module').then(m => m.NewModuleModule) },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Now let's clarify some things about relative routes. There are two types of routes, absolute and relative. The absolute routes start with ' / ' and Angular will try to match them with routes defined in the app routing module no matter the module they are defined in. The relative routes however are relative to the module and the paths will be appended to the module path.

For example, our new module is defined at the route localhost:4200/new_module and in our module, we have an empty path. Since this path doesn't start with ' / ', the path to our new module component is is resolved by Angular as localhost:4200/new_module/' ' or shorter localhost:4200/new_module.

Screenshot from 20200802 145916.png

Clicking now on the link in the navbar will make our new component appear on the screen and as you can see the URL in the search bar changed to match our route for this component.

The end.


What would you like to see in the next episode? I have two ideas, one is a more in-depth look at Angular with some real-world examples taken from my project and the other is to make an article on designing elements with UIkit.

Which of those two do you think I should do?


Alexandru-Balan
Alexandru-Balan

Happily married to a wonderful woman. Linux enthusiast, software developer and hacker of all things. I may be stupid, but at least I won't try to scam you.


Pr0gram Failure
Pr0gram Failure

A blog dedicated to development subjects that every programmer deals with all the time. Simple things we all google and then ask ourselves "are we even developers?" or things we do when writing software that we are ashamed of and would never share with others. This blog is dedicated to the average Joe of programming.

Send a $0.01 microtip in crypto to the author, and earn yourself as you read!

20% to author / 80% to me.
We pay the tips from our rewards pool.