define

  • property
can.Map.prototype.define

{Object<String,attrDefinition>}

 

Defines the type, initial value, get, set, remove, and serialize behavior for attributes of a can.Map.

Object<String,attrDefinition>

A map of attribute names to attribute definition objects.

Use

The can.Map.define plugin allows you to completely control the behavior of attributes on a can.Map. To use it, you specify an define object that is a mapping of properties to attribute definitions. The following example specifies a Paginate Map:

var Paginate = can.Map.extend({
  define: {
    count: {
      type: "number",
      value: Infinity,
      // Keeps count above 0.
      set: function(newCount){
        return newCount < 0 ? 0 : newCount;
      }
    },
    offset: {
      type: "number",
      value: 0,
      // Keeps offset between 0 and count
      set: function(newOffset){
        var count = this.attr("count");
        return newOffset < 0 ?
          0 :
          Math.min(newOffset, !isNaN( count - 1) ?
            count - 1 :
            Infinity);
      }
    },
    limit: {
      type: "number",
      value: 5
    },
    page: {
      // Setting page changes the offset
      set: function(newVal){
        this.attr('offset', (parseInt(newVal) - 1) * 
                             this.attr('limit'));
      },
      // The page value is derived from offset and limit.
      get: function (newVal) {
        return Math.floor(this.attr('offset') / 
                          this.attr('limit')) + 1;
      }
    }
  }
});

Default behaviors

The can.Map.define plugin not only allows you to define individual attribute behaviors on a can.Map, but you can also define default behaviors that would apply to any unspecified attribute. This is particularly helpful for when you need a particular behavior to apply to every attribute on a can.Map but won't be certain of what every attribute will be.

The following example is a can.Map that is tied to can.route where only specified attributes that are serialized will be updated in the location hash:

var State = can.Map.extend({
  define: {
    foo: {
      serialize: true
    },
    '*': {
      serialize: false
    }
  }
});

var state = new State();

// tie State map to the route
can.route.map(state);
can.route.ready();

state.attr('foo', 'bar');
state.attr('bar', 'baz');

window.location.hash; // -> #!foo=bar

Overview

This plugin is a replacement for the now deprecated attributes and setter plugins. It intends to provide a single place to define the behavior of all the properties of a can.Map.

Here is the cliffnotes version of this plugin. To define...

  • The default value for a property - use value
  • That default value as a constructor function - use Value
  • What value is returned when a property is read - use get
  • Behavior when a property is set - use set
  • How a property is serialized when serialize is called on it - use serialize
  • Behavior when a property is removed - use remove
  • A custom converter method or a pre-defined standard converter called whenever a property is set - use type
  • That custom converter method as a constructor function - use Type

Inheritance

can.Map constructors can inherit values from the can.Map.define plugin. If a parent can.Map constructor has a define property and a child constructor extends the parent and also has a define property, the two will be merged together so define properties from the parent are also available on instances of the child. For example:

var ParentMap = can.Map.extend({
  define: {
    inheritedProp: {
      get: function() {
        return 15;
      },
      set: function(newVal) {
        return newVal;
      }
    },
    parentProp: {
      get: function() {
        return 15;
      }
    }
  }
});
var ChildMap = ParentMap.extend({
  define: {
    childProp: {
      get: function() {
        return 22;
      }
    },
    inheritedProp: {
      get: function() {
        return 22;
      }
    }
  }
});

var map = new ChildMap();

map.attr('childProp'); // -> 22
map.attr('inheritedProp'); // -> 22
map.attr('parentProp'); // -> 15

map.attr('inheritedProp', 13); // -> calls ParentMap’s setter for inheritedProp

Demo

The following shows picking cars by make / model / year: