viewModel
{Object | can.Map | function(attrs, parentScope, element)}
Provides or describes a can.Map constructor function or can.Map
instance that will be
used to retrieve values found in the component's template. The map
instance is initialized with values specified by the component element's attributes.
Note: This page documents behavior of components in can.stache. can.mustache behaves slightly differently. If you want the behavior of components with can.mustache, please look at versions of this page prior to 2.3. In 2.3, use can.view.bindings {to-child}, {^to-parent} and {(two-way)} to setup viewModel bindings.
Use
can.Component's viewModel property is used to define an object, typically an instance of a can.Map, that will be used to render the component's template. This is most easily understood with an example. The following component shows the current page number based off a
limit
andoffset
value:If this component HTML was inserted into the page like:
It would result in:
This is because the provided viewModel object is used to extend a can.Map like:
Any primitives found on a
can.Map
's prototype (ex:offset: 0
) are used as default values.Next, a new instance of CustomMap is created with the attribute data within
<my-paginate>
(in this case there is none) like:And finally, that data is added to the parentScope of the component, used to render the component's template, and inserted into the element:
Values passed from attributes
Values can be "passed" into the viewModel of a component, similar to passing arguments into a function. Using can.view.bindings, the following binding types can be setup:
As mentioned in the deprecation warning above, using can.stache, values are passed into components like this:
The above would create an offset and limit property on the component that are initialized to whatever index and size are, NOT two-way bind (between component and parent viewModels) the offset and limit properties to the index and size.
The following component requires an
offset
andlimit
:If
<my-paginate>
's source html is rendered like:...
pageInfo
's index and size are set as the component's offset and limit attributes. If we were to change the value ofpageInfo
's index like:... the component's offset value will change and its template will update to:
Using attribute values
You can also pass a literal string value of the attribute. To do this in can.stache, simply pass any value not wrapped in single brackets, and the viewModel property will be initialized to this string value:
The above will create a title property in the component's viewModel, which has a string
hello
.If the tag's
title
attribute is changed, it updates the viewModel property automatically. This can be seen in the following example:Clicking the Change title button sets a
<panel>
element'stitle
attribute like:Calling methods on viewModel from events within the template
Using html attributes like
can-EVENT-METHOD
, you can directly call a viewModel method from a template. For example, we can make<my-paginate>
elements include a next button that calls the viewModel'snext
method like:viewModel methods get called back with the current context, the element that you are listening to and the event that triggered the callback.
Publishing events on viewModels
Maps can publish events on themselves. For instance, the following
<player-edit>
component, dispatches a"close"
event when it's close method is called:These can be listened to with (event) bindings like:
The following demo uses this ability to create a close button that hides the player editor: