Define Todo List page
Define Todo.List type (DefineList basics)
The problem
- Define a
Todo.List
type on the export of models/todo.js, where:- It is a DefineList type.
- The enumerable indexes are coerced into
Todo
types. - Its
.active
property returns a filteredTodo.List
of the todos that are not complete. - Its
.complete
property returns a filteredTodo.List
of the todos that are complete. - Its
.allComplete
property true if all the todos are complete.
Example test code:
QUnit.ok(Todo.List, "Defined a List");
const todos = new Todo.List([
{complete: true},
{},
{complete: true}
]);
QUnit.ok(todos[0] instanceof Todo, "each item in a Todo.List is a Todo");
QUnit.equal(todos.active.length, 1);
QUnit.equal(todos.complete.length, 2);
QUnit.equal(todos.allComplete, false, "not allComplete");
todos[1].complete = true;
QUnit.equal(todos.allComplete, true, "allComplete");
What you need to know
DefineList.extend defines a new
ListType
.The # property defines the behavior of items in a list like:
DefineList.extend({ "#": {type: ItemType} })
The get behavior defines observable computed properties like:
DefineMap.extend({ propertyName: { get: function() { return this.otherProperty; } } })
filter can be used to filter a list into a new list:
list = new ListType([ // ... ]); list.filter(function(item) { return test(item); })
The solution
Click to see the solution
Update models/todo.js to the following:
// models/todo.js
import {DefineMap, DefineList} from "can";
const Todo = DefineMap.extend("Todo", {
id: "string",
name: "string",
complete: {
type: "boolean",
default: false
},
toggleComplete() {
this.complete = !this.complete;
}
});
Todo.List = DefineList.extend("TodoList", {
"#": Todo,
get active() {
return this.filter({
complete: false
});
},
get complete() {
return this.filter({
complete: true
});
},
get allComplete() {
return this.length === this.complete.length;
}
});
export default Todo;