DoneJS StealJS jQuery++ FuncUnit DocumentJS
6.0.1
5.33.2 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
      • 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
        • behaviors
          • async
          • default
          • enumerable
          • get
          • get default()
          • identity
          • required
          • serialize
          • set
          • type
          • value
        • static
          • propertyDefaults
          • props
          • seal
        • prototype
          • get property()
          • set property()
        • types
          • DefinitionObject
          • Property
      • 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-model
      • can-view-parser
      • can-view-scope
      • can-view-target
      • steal-stache
    • Data Modeling
      • can-connect
      • can-connect-feathers
      • 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
      • 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-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

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:

import { ObservableObject } from "can/everything";

class Person extends ObservableObject {
  static props = {
    name: String,
    nameChangeCount: {
      value({ listenTo, resolve }) {
        let count = 0;

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

const p = new Person();
p.on( "nameChangeCount", ( ev, newValue ) => {
  console.log( "name changed " + newValue + " 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 {can-observable-object/define/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 can-observable-object. 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:

      import { ObservableObject } from "can/everything";
      
      class Example extends ObservableObject {
        static props = {
          property: {
            value( { lastSet, listenTo, resolve } ) {
      
              console.log( lastSet.get() ); //-> "test"
      
              // Set `property` initial value to set value.
              resolve( lastSet.get() );
      
              // When the property is set, update `property`.
              listenTo( lastSet, resolve );
            }
          }
        };
      }
      
      const e = new Example();
      e.property = "test";
      e.serialize();
      

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:

import { ObservableObject } from "can/everything";

class Timer extends ObservableObject {
  static props = {
    time: {
      value( { resolve } ) {
        resolve( new Date() );

        const interval = setInterval( () => {

          const date = new Date()
          console.log( date.getSeconds() ); //-> logs a new date every second

          resolve( date );
        }, 1000 );

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

const timer = new Timer();
timer.listenTo( "time", () => {} );

setTimeout( () => {
  timer.stopListening( "time" );
}, 5000 ); //-> stops logging after five seconds

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.

Our next example shows how get should be used with the fullName property. The following creates a fullName property that derives its value from the instantaneous first and last values:

import { ObservableObject } from "can/everything";

class Person extends ObservableObject {
  static props = {
    first: String,
    last: String
  };

  get fullName() {
    return this.first + " " + this.last;
  }
}

const p = new Person({ first: "John", last: "Smith" });
console.log( p.fullName ); //-> "John Smith"

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:

import { ObservableObject } from "can/everything";

class Person extends ObservableObject {
  static props = {
    first: String,
    last: String,
    fullName: {
      get() {
        return this.first + " " + this.last;
      }
    },
    fullNameChangeCount: {
      value( { listenTo, resolve } ) {
        let count = 0;
        resolve( 0 );
        listenTo( "fullName", () => {
          resolve( ++count );
        } );
      }
    }
  };
}

const p = new Person({ first: "John", last: "Smith" });
p.on("fullNameChangeCount", () => {});
p.first = "Justin";
p.last = "Meyer";
console.log(p.fullNameChangeCount); //-> 2

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

On this page

Get help

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