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 a Boolean that defaults to false.
    • It has a toggleComplete method that flips complete 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 Basics Presentation

  • 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
    
- The type behavior defines a property’s type like:
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;