PropDefinition
Defines the type, initial value, and get, set, and serialize behavior for an
observable property. These behaviors can be specified with as an Object
, String
,
Constructor
function, Array
, a getter expression
, or setter expression
.
Object
Defines multiple behaviors for a single property.
{
propertyName: {
default: function() { /* ... */ },
Default: Constructor,
type: function() { /* ... */ },
Type: Constructor,
get: function() { /* ... */ },
value: function() { /* ... */ },
set: function() { /* ... */ },
serialize: function() { /* ... */ },
identity: Boolean
}
}
function()
Either creates a method or Defines a Type setting with a constructor function. Constructor functions are identified with isConstructorLike.
{
propertyName: Constructor
}
OR
{
propertyName: function() {}
}
For example:
{
subMap: DefineMap // <- sets Type to DefineMap
}
OR
{
increment: function() {
++this.count;
} // <- sets method prop
}
Array
Defines an inline can-define/list/list Type setting. This is used as a shorthand for creating a property that is an can-define/list/list of another type.
{
propertyName: [Constructor | propDefinitions]
}
For example:
import {DefineMap} from "can";
const User = DefineMap.extend( {username: "string", password: "string"} );
const TodoList = DefineMap.extend( {
users: [ User ],
todos: [ { complete: "boolean", name: "string" } ]
} );
const user1 = new User( {username: "JMeyers", password: "12345"} );
const user2 = new User( {username: "PStrozak", password: "54321"} );
const myList = new TodoList( {
users: [ user1, user2 ],
todos: [ {complete: true, name: "Write this example"} ]
} );
console.log( myList.serialize() );
GETTER
Defines a property's get behavior with the syntax.
import {DefineMap} from "can";
const Example = DefineMap.extend( {
get propertyName() { return true; }
} );
const e = new Example();
console.log( e.propertyName ); //-> true
For example:
import {DefineMap} from "can";
const Person = DefineMap.extend( {
first: "string",
last: "string",
get fullName() {
return this.first + " " + this.last;
}
} );
const person = new Person( {first: "Justin", last: "Meyer"} );
console.log( person.fullName ); //-> "Justin Meyer"
This is a shorthand for providing an object with a get
property like:
import {DefineMap} from "can";
const Person = DefineMap.extend( {
first: "string",
last: "string",
fullName: {
get: function() {
return this.first + " " + this.last;
}
}
} );
const person = new Person( {first: "Justin", last: "Meyer"} );
console.log( person.fullName ); //-> "Justin Meyer"
You must use an object with a get property if you want your get to take the lastSetValue
or resolve
arguments.
SETTER
Defines a property's set behavior with the set syntax.
{
set propertyName( newValue ) { /* ... */ }
}
For example:
import {DefineMap} from "can";
const Person = DefineMap.extend( {
fullName: {
set(newValue) {
const parts = newValue.split(" ");
this.first = parts[0];
this.last = parts[1];
}
}
} );
const person = new Person( {fullName: "Justin Meyer"} );
console.log( person.first ); //-> "Justin"
console.log( person.last ); //-> "Meyer"
This is a shorthand for providing an object with a set
property like:
import {DefineMap} from "can";
const Person = DefineMap.extend( {
fullName: {
set: function(newValue) {
const parts = newValue.split(" ");
this.first = parts[0];
this.last = parts[1];
}
}
} );
const person = new Person( {fullName: "Justin Meyer"} );
console.log( person.first ); //-> "Justin"
console.log( person.last ); //-> "Meyer"
You must use an object with a set property if you want your set to take the resolve
argument.
Use
A property definition can be defined in several ways. The Object
form is the most literal
and directly represents a PropDefinition
object. The other forms
get converted to a PropDefinition
as follows:
DefineMap.extend( {
propertyA: Object, // -> PropertyDefinition
propertyB: String, // -> {type: String}
propertyC: Constructor, // -> {Type: Constructor}
propertyD: [ PropDefs ], // -> {Type: DefineList.extend({"#": PropDefs})>}
get propertyE() { /* ... */ }, // -> {get: propertyE(){ /* ... */ }}
set propertyF( value ) { /* ... */ }, // -> {set: propertyF(value){ /* ... */ }},
method: Function
} );
Within a property definition, the available properties and their signatures look like:
DefineMap.extend({
property: {
get: function(lastSetValue, resolve){...},
set: function(newValue, resolve){...},
type: function(newValue, prop){...}| Array<PropertyDefinition> | PropertyDefinition,
Type: Constructor | Array<PropertyDefinition> | PropertyDefinition,
default: function(){...},
Default: Constructor,
serialize: Boolean | function(){...}
}
})
For example:
import {DefineMap} from "can";
const Address = DefineMap.extend( "Address", {
street: "string",
state: "string"
} );
const Person = DefineMap.extend( "Person", {
// a `DefineList` of `Address`
addresses: [ Address ],
// A `DefineMap` with a `first` and `last` property
name: { type: { first: "string", last: "string" } },
// A `DefineList of a ``DefineMap` with a `make` and `year` property.
cars: { Type: [ { make: "string", year: "number" } ] }
} );
const person = new Person( {
addresses: [ { street: "1134 Pinetree" } ],
name: { first: "Kath", last: "Iann" },
cars: [ { make: "Nissan", year: 2010 } ]
} );
console.log(person.addresses[0].street); //-> "1134 Pinetree"
console.log(person.name.first); //-> "Kath"
console.log(person.cars[0].make); //-> "Nissan"