DoneJS StealJS jQuery++ FuncUnit DocumentJS
6.6.1
5.33.3 4.3.0 3.14.1 2.3.35
  • About
  • Guides
  • API Docs
  • Community
  • Contributing
  • Bitovi
    • Bitovi.com
    • Blog
    • Design
    • Development
    • Training
    • Open Source
    • About
    • Contact Us
  • About
  • Guides
  • API Docs
    • Observables
      • can-bind
      • can-compute
      • can-debug
      • can-deep-observable
      • can-define
        • static
          • types
        • types
          • PropDefinition
          • ValueOptions
        • behaviors
          • default
          • Default
          • get
          • identity
          • serialize
          • set
          • type
          • Type
          • value
      • can-define/list/list
      • can-define/map/map
      • can-define-backup
      • can-define-stream
      • can-define-stream-kefir
      • can-event-queue
      • can-kefir
      • can-list
      • can-map
      • can-map-compat
      • can-map-define
      • can-observable-array
      • can-observable-object
      • can-observation
      • can-observation-recorder
      • can-observe
      • can-simple-map
      • can-simple-observable
      • can-stream
      • can-stream-kefir
      • can-value
    • Views
      • can-attribute-observable
      • can-component
      • can-observable-bindings
      • can-stache
      • can-stache-bindings
      • can-stache-converters
      • can-stache-element
      • can-stache-route-helpers
      • can-view-autorender
      • can-view-callbacks
      • can-view-import
      • can-view-live
      • can-view-model
      • can-view-parser
      • can-view-scope
      • can-view-target
      • steal-stache
    • Data Modeling
      • can-connect
      • can-connect-ndjson
      • can-connect-tag
      • can-define-realtime-rest-model
      • can-define-rest-model
      • can-fixture
      • can-fixture-socket
      • can-local-store
      • can-memory-store
      • can-ndjson-stream
      • can-query-logic
      • can-realtime-rest-model
      • can-rest-model
      • can-set-legacy
      • can-super-model
    • Routing
      • can-deparam
      • can-param
      • can-route
      • can-route-hash
      • can-route-mock
      • can-route-pushstate
    • JS Utilities
      • can-assign
      • can-define-lazy-value
      • can-diff
      • can-globals
      • can-join-uris
      • can-key
      • can-key-tree
      • can-make-map
      • can-parse-uri
      • can-queues
      • can-string
      • can-string-to-any
    • DOM Utilities
      • can-ajax
      • can-attribute-encoder
      • can-child-nodes
      • can-control
      • can-dom-data
      • can-dom-events
      • can-dom-mutate
      • can-event-dom-enter
      • can-event-dom-radiochange
      • can-fragment
    • Data Validation
      • can-type
      • can-validate
      • can-validate-interface
      • can-validate-legacy
      • can-validate-validatejs
    • Typed Data
      • can-cid
      • can-construct
      • can-construct-super
      • can-data-types
      • can-namespace
      • can-reflect
      • can-reflect-dependencies
      • can-reflect-promise
      • can-types
    • Polyfills
      • can-symbol
      • can-vdom
    • Core
    • Infrastructure
      • can-global
      • can-test-helpers
    • Ecosystem
    • Legacy
  • Community
  • Contributing
  • GitHub
  • Twitter
  • Chat
  • Forum
  • News
Bitovi

PropDefinition

  • Edit on GitHub

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
    }
}

Options

  • default {default()}:

    Specifies the initial value of the property or a function that returns the initial value.

    import {DefineMap} from "can";
    
    // A default age of `0`:
    const Person = DefineMap.extend( {
        age: {
            default: 0
        },
        address: {
            default: function() {
                return { city: "Chicago", state: "IL" };
            }
        }
    } );
    
    const person = new Person();
    console.log( person.age ); //->  0
    
  • Default {Default()}:

    Specifies a function that will be called with new whose result is set as the initial value of the attribute.

    import {DefineMap, DefineList} from "can";
    
    // A default empty DefineList of hobbies:
    const Person = DefineMap.extend( {
      hobbies: { Default: DefineList }
    } );
    
    const person = new Person();
    console.log( person.hobbies instanceof DefineList ); //-> true
    
  • type {type()}:

    Specifies the type of the property. The type can be specified as either a function that returns the type coerced value or one of the types names.

    import {DefineMap} from "can";
    
    const Person = DefineMap.extend( {
      age: { type: "number" },
      hobbies: {
        type: function( newValue ) {
          if ( typeof newValue === "string" ) {
            return newValue.split( "," );
          } else if ( Array.isArray( newValue ) ) {
            return newValue;
          }
        }
      }
    } );
    
    const person = new Person({ age: "20", hobbies: "basketball,billiards,dancing" });
    console.log( person.age, person.hobbies ); //-> 20, ["basketball", "billiards", "dancing"]
    
  • Type {Type()}:

    A constructor function that takes the assigned property value as the first argument and called with new. For example, the following will call new Address(newValue) with whatever non null, undefined, or address type is set as a Person's address property.

    import {DefineMap} from "can";
    
    const Address = DefineMap.extend( {
      street: "string",
      state: "string"
    } );
    
    const Person = DefineMap.extend( {
      address: { Type: Address }
    } );
    
    const person = new Person({
        address: {
            street: "Example Ave.",
            state: "IL"
        }
    });
    console.log( person.address.serialize() ); //-> {state: "IL", street: "Example Ave."}
    
  • get {get(lastSetValue)}:

    A function that specifies how the value is retrieved. The get function is converted to an async compute. It should derive its value from other values on the object. The following defines a page getter that reads from a map's offset and limit:

    import {DefineMap} from "can";
    
    const Book = DefineMap.extend( {
      offset: "number",
      limit: "number",
      page: {
        get: function( newVal ) {
          return Math.floor( this.offset / this.limit ) + 1;
        }
      }
    } );
    
    const book = new Book( {offset: 10, limit: 5} );
    
    console.log( book.page ) //-> 3
    

    A get definition makes the property computed which means it will not be enumerable by default.

  • value {value()}:

    A function that listens to events and resolves the value of the property. This should be used when get is unable to model the right behavior. The following counts the number of times the page property changes:

    import {DefineMap} from "can";
    
    const Book = DefineMap.extend( {
      page: "number",
      pageChangeCount: {
        value( prop ) {
          let count = 0;
    
          // When page changes, update the count.
          prop.listenTo( "page", function() {
            prop.resolve( ++count );
          } );
    
          // Set initial count.
          prop.resolve( count );
        }
      }
    } );
    const book = new Book();
    book.on("pageChangeCount", () => {});
    book.page = 1;
    book.page += 1;
    console.log( book.pageChangeCount ); //-> 2
    

    A value definition makes the property computed which means it will not be enumerable by default.

  • set {set(newVal, resolve)}:

    A set function that specifies what should happen when a property is set. set is called with the result of type or Type. The following defines a page setter that updates the map's offset:

    import {DefineMap} from "can";
    
    const Book = DefineMap.extend( {
      offset: "number",
      limit: "number",
      page: {
        set: function( newVal ) {
          this.offset = ( parseInt( newVal ) - 1 ) * this.limit;
        }
      }
    } );
    
    const book = new Book({ limit: 5 });
    book.page = 10;
    console.log( book.offset ); //-> 45
    
  • serialize {serialize()}:

    Specifies the behavior of the property when serialize is called.

    By default, serialize does not include computed values. Properties with a get definition are computed and therefore are not added to the result. Non-computed properties values are serialized if possible and added to the result.

    import {DefineMap} from "can";
    
    const Todo = DefineMap.extend( {
      date: {
        type: "date",
        serialize: function( value ) {
          return value.getTime();
        }
      }
    } );
    
    const todo = new Todo( {date: Date.now()} );
    console.log( todo.serialize() ); //-> {date: 1535751516915}
    
  • identity {identity}:

    Specifies the property that uniquely identifies instances of the type.

    import {DefineMap, Reflect} from "can";
    
    const Grade = DefineMap.extend( "Grade", {
      classId: {type: "number", identity: true},
      studentId: {type: "number", identity: true},
      grade: "string"
    } );
    
    const myGrade = new Grade( {classId: 12345, studentId: 54321, grade: "A+"} )
    console.log(Reflect.getIdentity(myGrade)); //-> "{'classId':12345,'studentId':54321}"
    

String

Defines a type converter as one of the named types in types.

{
  propertyName: "typeName"
}

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"

CanJS is part of DoneJS. Created and maintained by the core DoneJS team and Bitovi. Currently 6.6.1.

On this page

Get help

  • Chat with us
  • File an issue
  • Ask questions
  • Read latest news