DoneJS StealJS jQuery++ FuncUnit DocumentJS
4.3.0
5.0.0 3.13.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-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-define
      • can-observation
      • can-observation-recorder
      • can-observe
      • can-simple-map
      • can-simple-observable
      • can-stream
      • can-stream-kefir
      • can-value
    • Data Modeling
      • can-connect
      • can-connect-feathers
      • can-fixture
      • can-fixture-socket
      • can-ndjson-stream
      • can-set
    • Views
      • can-component
      • can-stache
      • can-stache-bindings
      • can-stache-converters
      • can-stache-route-helpers
      • can-view-autorender
      • can-view-callbacks
      • can-view-import
      • can-view-live
      • can-view-model
      • can-view-nodelist
      • can-view-parser
      • can-view-scope
      • can-view-target
      • react-view-model
      • react-view-model/component
      • steal-stache
    • 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
      • can-util
      • can-zone
      • can-zone-storage
    • 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-define-validate-validatejs
      • 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

value

  • Edit on GitHub

Specify the behavior of a property by listening to changes in other properties.

value(prop)

The value behavior is used to compose a property value from events dispatched by other properties on the map. It's similar to get, but can be used to build property behaviors that get can not provide.

value enables techniques very similar to using event streams and functional reactive programming. Use prop.listenTo to listen to events dispatched on the map or other observables, prop.stopListening to stop listening to those events if needed, and prop.resolve to set a new value on the observable. For example, the following counts the number of times the name property changed:

Person = DefineMap.extend( "Person", {
    name: "string",
    nameChangeCount: {
        value( prop ) {
            let count = 0;

            prop.listenTo( "name", () => {
                prop.resolve( ++count );
            } );

            prop.resolve( count );
        }
    }
} );

const p = new Person();
p.on( "nameChangedCount", ( ev, newVal )=> {
    console.log( "name changed", newVal, "times" );
} );

p.name = "Justin"; // logs name changed 1 times
p.name = "Ramiya"; // logs name changed 2 times

If the property defined by value is unbound, the value function will be called each time. Use prop.resolve synchronously to provide a value.

type, default, get, and set behaviors are ignored when value is present.

value properties are not enumerable by default.

Parameters

  1. prop {ValueOptions}:

    An object of methods and values used to specify the property behavior:

    • prop.resolve(value) {function(Any)} Sets the value of this property as value. During a batch, the last value passed to prop.resolve will be used as the value.

    • prop.listenTo(bindTarget, event, handler, queue) {function(Any,String,Fuction,String)} A function that sets up a binding that will be automatically torn-down when the value property is unbound. This prop.listenTo method is very similar to the listenTo method available on DefineMap. It differs only that it:

      • defaults bindings within the notifyQueue.
      • calls handlers with this as the instance.
      • localizes saved bindings to the property instead of the entire map.

      Examples:

      // Binds to the map's `name` event:
      prop.listenTo( "name", handler );
      
      // Binds to the todos `length` event:
      prop.listenTo( todos, "length", handler );
      
      // Binds to the `todos` `length` event in the mutate queue:
      prop.listenTo( todos, "length", handler, "mutate" );
      
      // Binds to an `onValue` emitter:
      prop.listenTo( observable, handler ); //
      
    • prop.stopListening(bindTarget, event, handler, queue) {function(Any,String,Fuction,String)} A function that removes bindings registered by the prop.listenTo argument. This prop.stopListening method is very similar to the stopListening method available on DefineMap. It differs only that it:

      • defaults to unbinding within the notifyQueue.
      • unbinds saved bindings by prop.listenTo.

      Examples:

      // Unbind all handlers bound using `listenTo`:
      prop.stopListening();
      
      // Unbind handlers to the map's `name` event:
      prop.stopListening( "name" );
      
      // Unbind a specific handler on the map's `name` event
      // registered in the "notify" queue.
      prop.stopListening( "name", handler );
      
      // Unbind all handlers bound to `todos` using `listenTo`:
      prop.stopListening( todos );
      
      // Unbind all `length` handlers bound to `todos`
      // using `listenTo`:
      prop.stopListening( todos, "length" );
      
      // Unbind all handlers to an `onValue` emitter:
      prop.stopListening( observable );
      
    • prop.lastSet {can-simple-observable} An observable value that gets set when this property is set. You can read its value or listen to when its value changes to derive the property value. The following makes property behave like a normal object property that can be get or set:

      {
        property: {
          value: function( prop ) {
      
            // Set `property` initial value to set value.
            prop.resolve( prop.lastSet.get() );
      
            // When the property is set, update `property`.
            prop.listenTo( prop.lastSet, prop.resolve );
          }
        }
      }
      

Returns

{function}:

An optional teardown function. If provided, the teardown function will be called when the property is unbound after stopListening() is used to remove all bindings.

The following time property increments every second. Notice how a function is returned to clear the interval when the property is returned:

const Timer = DefineMap.extend( "Timer", {
    time: {
        value( prop ) {
            prop.resolve( new Date() );

            const interval = setInterval( () => {
                prop.resolve( new Date() );
            }, 1000 );

            return () => {
                clearInterval( interval );
            };
        }
    }
} );

const timer = new Timer();
timer.on( "time", function( ev, newVal, oldVal ) {
    console.log( newVal ); //-> logs a new date every second
} );

Use

The value behavior should be used where the get behavior can not derive a property value from instantaneous values. This often happens in situations where the fact that something changes needs to saved in the state of the application.

Lets first see an example where get should be used, the ubiquitous fullName property. The following creates a fullName property that derives its value from the instantaneous first and last values:

DefineMap.extend( "Person", {
    first: "string",
    last: "string",
    get fullName() {
        return this.first + " " + this.last;
    }
} );

get is great for these types of values. But get is unable to derive property values based on the change of values or the passage of time.

The following fullNameChangeCount increments every time fullName changes:

DefineMap.extend( "Person", {
    first: "string",
    last: "string",
    fullName: {
        get() {
            return this.first + " " + this.last;
        }
    },
    fullNameChangeCount: {
        value( prop ) {
            let count = 0;
            prop.resolve( 0 );
            prop.listenTo( "fullName", ()=> {
                prop.resolve( ++count );
            } );
        }
    }
} );

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

On this page

Get help

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