Book Image

Hands-On Full Stack Web Development with Aurelia

By : Diego Argüelles Rojas, Erikson Murrugarra
Book Image

Hands-On Full Stack Web Development with Aurelia

By: Diego Argüelles Rojas, Erikson Murrugarra

Overview of this book

Hands-On Full Stack Web Development with Aurelia begins with a review of basic JavaScript concepts and the structure of an Aurelia application generated with the Aurelia-CLI tool. You will learn how to create interesting and intuitive application using the Aurelia-Materialize plugin, which implements the material design approach. Once you fully configure a FIFA World Cup 2018 app, you'll start creating the initial components through TDD practices and then develop backend services to process and store all the user data. This book lets you explore the NoSQL model and implement it using one of the most popular NoSQL databases, MongoDB, with some exciting libraries to make the experience effortless. You'll also be able to add some advanced behavior to your components, from managing the lifecycle properly to using dynamic binding, field validations, and the custom service layer. You will integrate your application with Google OAuth Service and learn best practices to secure your applications. Furthermore, you'll write UI Testing scripts to create high-quality Aurelia Apps and explore the most used tools to run end-to-end tests. In the concluding chapters, you'll be able to deploy your application to the Cloud and Docker containers. By the end of this book, you will have learned how to create rich applications using best practices and modern approaches.
Table of Contents (19 chapters)
Title Page
Copyright and Credits
Dedication
Packt Upsell
Foreword
Contributors
Preface
Index

World Cup app overview


Now it is time to talk about our application we will build together. Apart from our web application written, of course, in Aurelia, we also need a backend service to persist our data. For the backend service, we will be using Node.js with the Express framework to build a robust API and MongoDB as our non-relational data storage. The following diagram explains our World Cup project architecture:

This a very simple architecture; the Aurelia app talks to the Node API directly, and the Node API talks to the database, which is a MongoDB database, using a very popular open source library called Mongoose. This is getting better; keep reading!

Exploring the application features

The app we will develop is the Football World Cup app. We will use an awesome UI framework called Materialize, which, by default, will help us create a responsive web application, so our users can open this app in their mobile and desktop browser with an adaptable user interface.

Although this is a simple application, we will cover the most important concepts of Aurelia that you will find in a real production application. We will improve this app along with the book. Listed are the features we will develop for this app:

  • Matches explorer
  • Teams explorer
  • News
  • Admin portal
  • Social authentication

So, let's start exploring the features that this application delivers to our users.

Matches explorer

This feature is related to the matches in the entire competition. The users will be able to perform the following actions:

  • List the Matches activity
  • Create a new Match, which requires admin
Listing the matches

The user will see the list of matches represented as cards. A calendar is shown to the user to navigate and see the matches scheduled per day. The mock-up is shown here:

Creating a new Match

To create a new Match, an admin account is required. Once the user is authenticated, they can schedule a new Match by selecting the teams and the time. The mock-up is shown as follows:

Teams explorer

This feature is related to the matches in the entire competition. The users will be able to perform the following actions:

  • List the Teams
  • Create a new Team, which requires admin
Listing the teams

The user will see the list of teams represented as cards. The mock-up is as follows:

Creating a new team

To create a new Team, an admin account is required. Once the user is authenticated, they can create a new team. The mock-up is this:

News

This feature is related to the news. The users will be able to perform the following actions:

  • List the News
  • Create a New item, which requires admin
Listing the News

The user will see the list of news represented as cards. The mock-up is as shown:

Create a New

To create a New, an admin account is required. Once the user is authenticated, they can create a New. The mock-up is this:

Social authentication

The user will be able to sign in using their Google or Facebook account. The mock-up is this:

Now that we have an idea of the application we will develop, let's continue creating the initial application project.

Creating our app

Let's start creating our application. If you remember our last section about the Aurelia CLI, we need to use it again to create a new application, so open your favorite Terminal tool and execute the following command:

au new worldcup-app

Enter the following input in the Terminal:

  1. Select 3 to define our custom options for this project
  2. First option: Which module loader / bundler would you like to use? RequireJS (Default)

  3. Second option: What transpiler would you like to use? : Babel (Default)

  4. Third option: How would you like to setup your template? : Default(No markup processing.)

  5. Fourth option: What CSS processor would you like to use? In this case, we will choose Sass(3)

  6. Fifth option: Would you like to configure unit testing? Of course, we will mark Yes (Default)

  7. Sixth option: What is your default code editor?We use WebStorm, but you can choose the most familiar to you.

Now, you will see the main structure of your application on the console:

Project Configuration
    Name: worldcup-app
    Platform: Web
    Bundler: Aurelia-CLI
    Loader: RequireJS
    Transpiler: Babel
    Markup Processor: None
    CSS Processor: Sass
    Unit Test Runner: Karma
    Editor: WebStorm
  1. Finally, select  1 to create the project and then install the project dependencies

This is a custom setup. Our project will be composed with the following features:

  • RequireJS: Well known file and module loader, with a good browser support. Another option could be SystemJS and Webpack.
  • Babel: Babel is one of the most used transpilation tools nowadays. A transpiler is a tool that transforms code written in JavaScript ES6 syntax or later into ES5 code. Why? Because most of the browsers does not have well supported yet the last JavaScript version.
  • Markup processing: It loads our modules and create the final files which will be interpreted by the browser. We won't use a custom markup processing in this stage.
  • SASS: A nice preprocessor CSS library, we will review it at more detail in the next chapter.
  • Karma: A JavaScript test library. We will talk about it in more detail in the  Chapter 3, Testing and Debugging.
  • WebStorm: A very nice IDE for JavaScript developers. It is not free but if you have an educational email account from your university or institute, you can get a student license for one year. 

Once everything is done, open the worldcup-app folder with your favorite editor.

Note

We know Webpack is a very awesome module loader, but for learning purposes, we prefer to use RequireJS across all this book because is more simple and let us explain better how to configure manually  each tool and library we will use in this book.

The project structure

The Aurelia CLI will generate the source code with its base structure, which has everything configured and ready to start writing our application's source code.

The following screenshot shows the root application folder:

Let's start talking about the aurelia_project folder, which contains the main aurelia.json configuration file with all the settings about the dependencies, blunder, build target, loaders, testing run-time tool such as Karma, testing framework, and more. You will modify this file frequently to specify new dependencies our application needs to use.

The next element in the aurelia_folder is the environments folder, which contains three files: dev.json, stage.json, and prod.json. These files contain values depending on the environment you are running on. Do you remember the --env flag in the run option? The CLI will use one of these files to configure our app's environmental values.

The remaining two folders are generators and tasks. They are used to generate Aurelia custom reusable components and to declare gulp tasks, respectively.

The scripts folder contains the bundles generated after we execute the au build command.

As you might guess, the src folder contains our application source code, followed by the test folder, which contains our source code to test our project.

The Bootstrap process

Like many JavaScript frameworks such as Angular and React, Aurelia needs a place in the index.html page to mount the application. This place is known as the entry point. Open the index.html file, and you should see something similar to the following code:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Aurelia</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body aurelia-app="main">
<script src="scripts/vendor-bundle.js" data-main="aurelia-bootstrapper"></script>
</body>
</html>

Aurelia requires an HTML element to load our application. By default, the application is loaded in the body element; we know this because this element uses the aurelia-app attribute, which is used to specify the main JavaScript script file that contains all the configuration for our application, and as you note, by default, Aurelia is configured to use the main file. The following is the content of themain.jsfile:

import environment from './environment';

export function configure(aurelia) {
aurelia.use
.standardConfiguration()
    .feature('resources');

if (environment.debug) {
    aurelia.use.developmentLogging();
  }

if (environment.testing) {
    aurelia.use.plugin('aurelia-testing');
  }

aurelia.start().then(() => aurelia.setRoot());
}

Let's analyze this file; the first line imports the environment variables from the environment.js file located in the root folder. When you specify the --flag{env} option, the CLI looks for the {env}.json file in the aurelia_project folder and copies its content into the environment.js file.

This file also exports a single configure function, which receives as a parameter the aurelia object that you use to override default configurations and add any code you wish before the app is launched. For example, you can tell Aurelia that you want to declare components as global (features), configure internationalization to manage different languages, and so on.

Once the aurelia object is configured, the last line of code will render our application into the root HTML element, which has the aurelia-app attribute in the index.html page. By default, it renders the app.js component into the root element. Of course, we can override the default values by passing the element you wish to render as the first parameter and the HTML element where you wish to render the app as a second parameter:

 aurelia.start().then(() => aurelia.setRoot('my-component', document.getElementById('my-div')));

We will be modifying this file along the way; the most important thing to remember is that this file is processed before the app is rendered and apart from the Aurelia.json file, this is the second most important file. The following diagram explains the bootstrapping process:

Now you know how the bootstrapping process works. Let's understand how you can create reusable components.

Understanding components

In the last section, we saw that Aurelia requires a component to mount as the root of our entire application and by default, it was the app component. Now let's explore this component.

A component is composed of two files, the first written in JavaScript that contains the component's view model and the second one is the markup template written in HTML. They must have the same filename to help the view model resolve its view template. The component's view model is a JavaScript file, which exports a class that contains the component's attributes and functions. For example, this is the content of the app.js component:

export class App {
constructor() {
this.message = 'Hello World!';
  }
}

The App class declares a constructor that initializes the message property. Properties can be declared into the constructor or can be defined outside of it. Consider this example:

export class App {
  message = 'Hello World!';
}

Note

Use the outside property declaration style when you are declaring simple classes such as Plain Old CLR Objects (POCO), which now implements more logic than simply get and set its property values.

To use the properties defined in our app.js view model, we need an HTML template with the same filename. Open the app.html file to see its content:

<template>
<h1>${message}</h1>
</template>

The first thing to note is that the message property declared in the view model is present, but in order to bind the value, we have to use the ${}string interpolation operator. Finally, when Aurelia renders the component in the web page, the ${message} declaration will be replaced by 'Hello World!'.

We can extend our components by adding functions that can be called from the template. For example, let's declare the changeMessage() function:

export class App {

constructor() {
this.message = 'Hello World!';
  }

changeMessage() {
    this.message = 'World-Cup App';
  }

}

From the preceding code, you can see how declaring a function is a simple; we use the same syntax of the contructor declaration. If you want to use the properties declared in the App class, you have to use the this reserved word to access any property or function.

Now it is time to invoke our changeMessage function. First, we will create a button in our template in the app.html file and declare a trigger to the click event of the button. Open the app.html file and apply the following changes:

<template>
<h1>${message}</h1>
<button click.trigger="changeMessage()">Change</button>
</template>

The first thing to note here is that we don't use the default HTML onclick event; instead, we use the click event with no on at the start of the event name. This convention is used only for the Aurelia templating engine. So, we say that we want to invoke the changeMessage() functions by binding this function to the click event using the trigger binding mechanism.

Launch your app by executing the au run command in your Terminal, and test this out. When you click on the Change button, you should see how the message is changed from 'Hello World!' to 'World-Cup' App. The h1 HTML element is changed because we have previously declared and bound the ${message} property into its content.

Binding is a big concept we will cover in next chapters in a more detailed way. So, keep reading my friend, it just starting.