Taken from here:
- Use modern JavaScript and TypeScript - fully written in standards-based ES 2015 and ES 2016
- Designed to work with modern ES 2015-oriented package managers like JSPM.
- Intended to be used with modern transpilers such as Babel and TypeScript.
- Leverages standards-compliant Web Components specs such as HTMLTemplateElement and ShadowDOM
- Highly modular development, suitable for large-scale apps
- Designed for modern web browsers.
- Adds polyfills to support older browsers, such as IE9.
- Fully-extensible and adaptive data-binding engine.
- Powerful and flexible hierarchical dependency injection.
- Leverage conventions to write less code and get more done.
- Little to no framework intrusion, so developers can focus on their app, not the framework.
- Application and package bundling compatible with any build system.
In this tutorial we will primarily be using the Aurelia CLI. Prerequisites for this are
- NodeJS version 4.x or above
- Git
Once you have those prerequisites installed you can install the Aurelia CLI itself by running the following command on the command line:
npm install aurelia-cli -g
- Run
au newon the command line. Take option2. Default TypeScriptand accept all other defaults. - Change directory to the newly created
aurelia-appfolder and runau run --watch. - Wait for the build to be finished, open a web browser and navigate to http://localhost:9000. You should see a web page displaying "Hello World!".
- Replace
<h1>${message}</h1>inapp.htmlwith<router-view></router-view>. - Add
configureRouter(config, router)function inapp.tsand remove the message. Full code for the function:
configureRouter(config: RouterConfiguration, router: Router): void {
this.router = router;
config.title = 'Aurelia';
config.map([
{ route: ['', 'todo'], name: 'todo-list', moduleId: 'routes/todo/todo' },
{ route: 'todo/add', name: 'add-todo', moduleId: 'routes/todo/add' }
]);
}
- Add
routes/todo/todo.htmlwith the following content:
<template>
<h3>Todos</h3>
</template>
- Add
routes/todo/todo.tswith the following content:
export class Todo {
}
- Add
routes/todo/todo-model.tswith the following content:
export class TodoModel {
constructor(private description: string, private deadline: string, private priority: string) {
}
}
- Add a new component with
routes/todo/add.htmlandroutes/todo/add.ts.
add.html:
<template>
<h3>Todos</h3>
<h4>Add new todo</h4>
<form>
<input type="text">
<input type="date">
<select>
<option>High</option>
<option>Medium</option>
<option>Low</option>
</select>
<button type="submit">Add todo</button>
</form>
</template>
add.ts:
export class Add {
}
- Add
routes/todo/todo-service.tswith the following content:
import { TodoModel } from './todo-model';
export class TodoService {
todoList: Array<TodoModel> = [];
constructor() {
}
}
- Add TodoService injection to
routes/todo/todo.tsandroutes/todo/add.ts. To do this, extend both files with the following parts:
At the top of the file add:
import { TodoService } from './todo-service';
Import the autoinject decorator and at the top of each class and use it above the class declaration:
import { autoinject } from 'aurelia-framework';
@autoinject()
Add/extend the constructor for each class:
constructor(private todoService: TodoService) {
}
- Add navigation from todo to add-todo. Add the following in
routes/todo/todo.html:
<a route-href="route: add-todo">Add new todo</a>
- Add event binding to the form in
routes/todo/add.html:
...
<form submit.delegate="addTodo()">
...
- Add event handler in
routes/todo/add.ts:
...
addTodo() {
}
...
- Add property initializer and call it in constructor of
routes/todo/add.ts:
...
description: string;
priority: string;
deadline: Date;
constructor(private todoService: TodoService) {
this.description = '';
this.priority = 'Medium';
this.deadline = new Date().toISOString().substring(0, 10);
}
...
- Add data binding in
routes/todo/add.html:
<template>
<h3>Todos</h3>
<h4>Add new todo</h4>
<form submit.delegate="addTodo()">
<input type="text" value.bind="description">
<input type="date" value.bind="deadline">
<select value.bind="priority">
<option>High</option>
<option>Medium</option>
<option>Low</option>
</select>
<button type="submit">Add todo</button>
</form>
</template>
- Implement
addTodo()inroutes/todo/add.ts:
import { TodoModel } from './todo-model';
...
addTodo() {
let todo = new Todo(this.description, this.deadline, this.priority);
this.todoService.todos.push(todo);
}
- Add an automatic redirect in
addTodo()inroutes/todo/add.ts:
import { Router } from 'aurelia-router';
...
...
constructor(private todoService: TodoService, private router: Router) {
...
}
...
addTodo() {
let todo = new Todo(this.description, this.deadline, this.priority);
this.todoService.todos.push(todo);
this.router.navigateToRoute('Todos');
}
- Add template and getter for todos in
routes/todo/todo.htmlrespectivelyroutes/todo/todo.ts:
todo/todo.html:
<template>
<h3>Todos</h3>
<a route-href="route: add-todo">Add new todo</a>
<ul>
<li repeat.for="todo of todos">
${todo.description} - ${todo.deadline} - ${todo.priority}
</li>
</ul>
</template>
todo/todo.ts:
get todos() {
return this.todoService.todos;
}
- Add
resources/elements/todo-item.ts:
import { bindable } from 'aurelia-framework';
export class TodoItemCustomElement {
@bindable item;
constructor() {
this.item = {};
}
}
- Add
resources/elements/todo-item.html:
<template>
${item.description} - ${item.deadline} - ${item.priority}
</template>
- Add require and usage of custom element in
routes/todo/todo.html:
<template>
<require from="resources/elements/todo-item"></require>
...
<todo-item item.bind="todo"></todo-item>
...
- Add done button in
resources/elements/todo-item.html:
<template>
${item.description} - ${item.deadline} - ${item.priority}
<button click.delegate="done()">Done</button>
</template>
- Add done handler in
resources/elements/todo-item.ts:
...
done() {
this.item.done = true;
}
...
- Add
resources/elements/todo-item.css:
.done {
text-decoration: line-through;
}
- Add require for new css file and class binding in
resources/elements/todo-item.html. Addshow.bindin button:
<template>
<require from="./todo-item.css"></require>
<span class="${item.done ? 'done' : ''}">
${item.description} - ${item.deadline} - ${item.priority}
</span>
<button show.bind="!item.done" click.delegate="done()">Done</button>
</template>