Routing page
Set up routing (can-route)
Make it so that the following URLs display the corresponding todos:
#!
or- All todos
#!active
- Only the incomplete todos#!complete
- Only the completed todos
Also, the All, Active, and Completed buttons should
link to those pages and a class="selected"
property should
be added if they represent the current page.
What you need to know
route is used to connect a
DefineMap
’s properties to the URL. This is done with route.data like:route.data = new DefineMap();
route can create pretty routing rules. For example, if
#!login
should set thepage
property of theAppViewModel
to"login"
, useroute.register()
like:route.register("{page}");
route.start() initializes the connection between the URL and the
AppViewModel
. After you’ve created all your application’s pretty routing rules, call it like:route.start()
The can-stache-route-helpers module provides helpers that use route.
routeCurrent returns truthy if the current route matches its first parameters properties.
{{# if(routeCurrent(page='login',true)) }} You are on the login page. {{/ if }}
routeUrl returns a URL that will set its first parameters properties:
<a href="{{ routeUrl(page='login') }}">Login</a>
The solution
Click to see the solution
Update index.js to the following:
// index.js
import {Component, route, DefineMap} from "can";
import view from "./index.stache";
import Todo from "~/models/todo";
import "~/models/todos-fixture";
import test from "can-todomvc-test";
route.register("{filter}");
Component.extend({
tag: "todo-mvc",
view,
ViewModel: {
appName: {default: "TodoMVC"},
routeData: {
default(){
route.start();
return route.data;
}
},
allTodos: {
get: function(lastSet, resolve) {
Todo.getList({}).then(resolve);
}
},
get todosList() {
if(this.allTodos) {
if(this.routeData.filter === "complete") {
return this.allTodos.complete;
} else if(this.routeData.filter === "active") {
return this.allTodos.active;
} else {
return this.allTodos;
}
}
},
get allChecked() {
return this.todosList && this.todosList.allComplete;
},
set allChecked(newVal) {
this.todosList && this.todosList.updateCompleteTo(newVal);
}
}
});
const appVM = window.appVM = document.querySelector("todo-mvc").viewModel;
test(appVM);
Update index.stache to the following:
<!-- index.stache -->
<can-import from="~/components/todo-create/" />
<can-import from="~/components/todo-list/" />
<can-import from="can-stache-route-helpers" />
<section id="todoapp">
<header id="header">
<h1>{{ this.appName }}</h1>
<todo-create/>
</header>
<section id="main" class="">
<input id="toggle-all" type="checkbox"
checked:bind="this.allChecked"
disabled:from="this.todosList.saving.length" />
<label for="toggle-all">Mark all as complete</label>
<todo-list todos:from="this.todosList" />
</section>
<footer id="footer" class="">
<span id="todo-count">
<strong>{{ allTodos.active.length }}</strong> items left
</span>
<ul id="filters">
<li>
<a href="{{ routeUrl(filter=undefined) }}"
{{# routeCurrent(filter=undefined) }}class='selected'{{/ routeCurrent }}>
All
</a>
</li>
<li>
<a href="{{ routeUrl(filter='active') }}"
{{# routeCurrent(filter='active') }}class='selected'{{/ routeCurrent }}>
Active
</a>
</li>
<li>
<a href="{{ routeUrl(filter='complete') }}"
{{# routeCurrent(filter='complete') }}class='selected'{{/ routeCurrent }}>
Completed
</a>
</li>
</ul>
<button id="clear-completed"
on:click="allTodos.destroyComplete()">
Clear completed ({{ allTodos.complete.length }})
</button>
</footer>
</section>
Success! You’ve completed this guide. Have questions or comments? Join our Discord and let us know in the #canjs channel or our forums!