Define Todo Model page
Learn how to create an observable type in CanJS.
The problem
- Define a
Todo
type as the export of models/todo.js, where:- It is a DefineMap type.
- The id or name property values are coerced into a string.
- Its
complete
property is aBoolean
that defaults tofalse
. - It has a
toggleComplete
method that flipscomplete
to the opposite value.
Example test code:
const todo = new Todo({id: 1, name: 2});
QUnit.equal(todo.id, "1", "id is a string");
QUnit.equal(todo.name, "2", "name is a string");
QUnit.equal(todo.complete, false, "complete defaults to false");
todo.toggleComplete();
QUnit.equal(todo.complete, true, "toggleComplete works");
What you need to know
DefineMap.extend defines a new
Type
.import {DefineMap} from "can"; const MyType = DefineMap.extend("MyType",{}); var instance = new MyType(); console.log( instance instanceof MyType ) // Logs true
import {DefineMap} from "can";
const Person = DefineMap.extend("Person",{
age: {type: "number"}
});
console.log( new Person({age: "3"}).age ) // Logs 3
The default behavior defines a property’s initial value like:
import {DefineMap} from "can"; const Person = DefineMap.extend("Person",{ age: {default: 3} }); console.log( new Person().age ) // Logs 3
Methods can be defined directly on the prototype like:
import {DefineMap} from "can"; const Type = DefineMap.extend("Type",{ methodName() { console.log("run method"); } }); var instance = new Type(); instance.methodName() // Logs "run method"
The solution
Click to see the solution
Create models/todo.js as follows:
// models/todo.js
import {DefineMap} from "can";
const Todo = DefineMap.extend("Todo", {
id: "string",
name: "string",
complete: {
type: "boolean",
default: false
},
toggleComplete() {
this.complete = !this.complete;
}
});
export default Todo;