Time to practice!

It's time to start coding! At this point, we have our application created and running, preconfigured to use SASS as CSS preprocessor, and integrated with the Aurelia Materialize library to follow good design practices of Material Design. Now we need to define our layout. It will be very basic at this time and across the application growing, our developed components can be improved and refactorized.

First, we need to access our root folder application; once inside, we just need to type the following command:

au run --watch

Next, we open our favorite browser's window, which should look something like this:

Now, let's create our main layout. Inside the src folder, we will create a folder named layout. Inside this folder, to subfolders: header and menu:

  • ./src > layout > header >: Here, we will create an HTML file for view and JS file for view-model. Both files are called app-header
  • ./src > layout > menu >: Same way as the header, both files will be called app-menu

Our folder structure should look like this:

First, we'll create the app-header component. Let's open the HTML file and create our navbar header. It's at this point that we will see the Aurelia Materialize features:

<template>
<md-navbar>
<div class="margin-content">

<ul class="hide-on-med-and-down right">
<li md-waves><a href="#about">About</a></li>
<li md-waves><a href="#map">Login</a></li>
</ul>

</div>
</md-navbar>
</template>

<md-navbar> tag refers to the navbar element of Aurelia Materialize. This is very helpful because the components are already created; we just need to call them and start defining how we want to show to our user. We won't create any CSS class at this point. Inside our nav-bar, we are creating two navigation options just to see how it looks on the browser.

With our first component created, it's time to integrate it with our main page, app.html. First, we need to call the created component using the <require> tag:

<require from="./layout/header/app-header"></require>

Then, we just need to call the created component by its filename:

<app-header></app-header>

Now just reload your browser's window and... an error is raised! What to do in that case? What happened? Our best friend, the console, will tell us the truth:

DEBUG [templating] importing resources for app.html Array [ "materialize-css/css/materialize.css", "layout/header/app-header" ]
vendor-bundle.js:14222:8 TypeError: target is undefined[Learn More]

Let's pay attention to the last parts of each line. First, the error occurred when the Aurelia bootstrapper was importing and configuring our created component. The last message tells us the error cause: undefined target.

Think for a few minutes, what could have happened? We know you have enough knowledge to tell us what the error was.

Ready? If you note, our recently created view-model file for app-header.js is completely empty. So we have the view, but that view is not pointing to anything, and the target is undefined! To solve this error, we just need to declare the component name and export it:

export class AppHeader {

}

Now, let's reload our browser:

Awesome, right? Relax, this is just the beginning. Now it's time to create our menu.

Our chosen Materialize component is the fixed sidenav. However, to integrate this into our application, we will merge some of the techniques and concepts learned until now. First, let's code our component:

<template>

<md-sidenav view-model.ref="sideNav" md-fixed="true" md-edge="left">
<ul>
<li md-waves><a>Option A</a></li>
<li md-waves><a>This is better</a></li>
<li md-waves><a>I want this</a></li>
<li md-waves><a>Oops!</a></li>
</ul>
</md-sidenav>

</template>

Similarly, using the <require> tag, we will import it into our app.html file. If we just call the sidenav menu, we will get the following result:

Of course, we don't want to hide our main application content! It's time to start using CSS to make the app-menu play for our team.

First, let's add some container order to our app.html page. It should be something like this:

<template>
<require from="materialize-css/css/materialize.css"></require>
<require from="./layout/header/app-header"></require>
<require from="./layout/menu/app-menu"></require>

<app-header></app-header>

<main>

<div class="row">

<div class="col s12 m12 l12">
<h1>${message}</h1>
</div>

</div>

<app-menu></app-menu>

</main>

</template>

We are just involving our main content, in this case, the message property, into one container that fills the entire screen no matter the resolution.

If we run the application, we'll still be seeing the same result. We need to apply some custom CSS modifications to our sidenav component. It's time to start using SASS!

We have SASS on our dependencies path, and it's ready for use in our application, but let's add some modifications just to make our files distribution a little more understandable for us.

Go to the aurelia_project folder and open the task called process-css.js.

If you remember the Gulp task automation from the previous chapters, you'll find the code very familiar. We just need to add one single line:

export default function processCSS() {
return gulp.src(project.cssProcessor.source)
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./')) //THIS LINE
.pipe(build.bundle());
}

Why this line? We want to see the generated CSS file into our project and import it from our index.html file. Again, why? It's because using this file directly into your browser, your style modifications and debugging will be easier in case you need to modify or maintain the style sheets.

Then, let's create our styles folder. This should be located directly in our src folder. Could it be located in a different location? Sure, but we recommend that you first check your aurelia.json file.

If you search the cssProcessor task, you will find this:

"cssProcessor": {
"id": "sass",
"displayName": "Sass",
"fileExtension": ".scss",
"source": "src/**/*.scss"
},

The source property is indicating the level at which our scss files will be located, and guess where they are by default? Yes, the src/*whatever*/*.scss location. You can modify it, but for our current purpose, we don't need to.

Then, inside our folder, let's create our first .scss file called _mainlayout.scss. Remember that the _ prefix is to indicate that this style sheet will be used as part of another style sheet. We just need to add the following code:


header, main, footer {
padding-left: 300px;
}

md-navbar[md-fixed="true"] nav {
padding-right: 300px;
}

md-sidenav {
div {
collapsible-body {
}
padding: 0;
}
}

We are just telling our header and application main body to stay 300 px right from our app menu. Now, it's time to reload our browser:

Our base layout is done! Guess what? Yeah, its time to add routing!

Let's decouple the welcome message of the app.js file. Create a home component to render a custom message; we called it app-home. Now, instead of the <h2> tag in your app.html file, put the <router-view> tag.

In the app view-model file, delete the constructor method; we won't use it this time. Then, just add the following code:

configureRouter(config, router) {
this.router = router;
config.title = 'FIFA WC 2018';
config.map([
{ route: ['', 'home'], name: 'home', moduleId: 'home/app-home' },
]);
}

Now, let's reload our browser. Pay attention to the window title; it now reflects our application name!

For practice purposes, we are done by this time! If you note, we're mixing a lot of concerns in just some basic approaches to our application. Now, let's add the extra value to our code. Do you remember our hard-coded menu options? Don't you think it should be dynamic? Yes, we are talking about adding dynamic binding to our practice! What are you waiting for, open your app-menu view and view-model!

Let's create an array of string in the view-model layer. We will use the same options used in the image:

export class AppMenu {

menuOptions = [
'Option A',
'This is better',
'I want this',
'Oops!',
]

}

Next, the magic. The repeat command will do the dirty work for us. Okay, we know that we didn't mention it before; do you remember when we said we'll review a lot of new concerns when implementing a real application? This is one of those:

<template>

<md-sidenav view-model.ref="sideNav" md-fixed="true" md-edge="left">
<ul>

<li repeat.for="option of menuOptions" md-waves><a>${option}</a></li>

</ul>
</md-sidenav>

</template>

That was very easy. Now we are really done. Our FIFA WC 2018 App is ready to start writing our business services and components! One more thing is pending and that's the tests part. We won't cover it in practice, because in the next chapter, we will find some more complex components created for our application, and we will be nice to apply testing to real-life components.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset