Deprecated 2.1
In 2.1, can.stache and can.mustache pass values to the
scope differently. To pass data from the scope, you must wrap your attribute
value with {}
. In 3.0, can.mustache
will use can.stache
's syntax.
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.
Object
A plain JavaScript object that is used to define the prototype methods and properties of
constructor function that extends can.Map. For example:
can.Component.extend({
tag: "my-paginate",
scope: {
offset: 0,
limit: 20,
next: function(){
this.attr("offset", this.offset + this.limit);
}
}
})
Prototype properties that have values of "@"
are not looked up in the current scope, instead
the literal string value of the relevant attribute is used (like pass by value instead of pass by reference). For example:
can.Component.extend({
tag: "my-tag",
scope: {
title: "@"
},
template: "<h1>{{title}}</h1>"
});
With source HTML like:
<my-tag title="hello"></my-tag>
Results in:
<my-tag><h1>hello</h1></my-tag>
A can.Map
constructor function will be used to create an instance of the observable
can.Map
placed at the head of the template's scope. For example:
var Paginate = can.Map.extend({
offset: 0,
limit: 20,
next: function(){
this.attr("offset", this.offset + this.limit);
}
})
can.Component.extend({
tag: "my-paginate",
scope: Paginate
})
function(attrs, parentScope, element)
Returns the instance or constructor function of the object that will be added
to the scope.
Parameters
-
attrs
{Object}
An object of values specified by the custom element's attributes. For example,
a template rendered like:
can.mustache("<my-element title="name"></my-element>")({
name: "Justin"
})
Creates an instance of following control:
can.Component.extend({
tag: "my-element",
scope: function(attrs){
attrs.title //-> "Justin";
return new can.Map(attrs);
}
})
And calls the scope function with attrs
like {title: "Justin"}
.
-
The scope the custom tag was found within. By default, any attribute's values will
be looked up within the current scope, but if you want to add values without needing
the user to provide an attribute, you can set this up here. For example:
can.Component.extend({
tag: "my-element",
scope: function(attrs, parentScope){
return new can.Map({title: parentScope.attr('name')});
}
});
Notice how the attribute's value is looked up in my-element
's parent scope.
-
element
{HTMLElement}
The element the can.Component is going to be placed on. If you want
to add custom attribute handling, you can do that here. For example:
can.Component.extend({
tag: "my-element",
scope: function(attrs, parentScope, el){
return new can.Map({title: el.getAttribute('title')});
}
});
Returns
Specifies one of the following:
- The data used to render the component's template.
- The prototype of a
can.Map
that will be used to render the component's template.
-
If an instance of can.Map
is returned, that instance is placed
on top of the scope and used to render the component's template.
-
If a plain JavaScript object is returned, that is used as a prototype
definition used to extend can.Map
. A new instance of the extended Map is created.
Use
can.Component's scope 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 scope 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 scope of a component, similar to passing arguments into a function. By default, custom tag attributes (other than
class
andid
) are looked up in the parent scope and set as observable values on the can.Map instance.Values passed in this way are passed similar to function arguments that are "pass by reference" because they are crossbound to the property in the parent scope. Changes in the parent scope property that is passed in trigger changes in this component's scope property, and likewise, changes in the component's scope property trigger a change in the parent scope property.
As mentioned in the deprecation warning above, using can.stache, values are passed into components like this:
But using can.mustache, values are passed like this:
The rest of the examples in this section show
can.mustache
syntax (which will change to match can.stache in 3.0).Note that using double brackets would instead render the string version of the value, and pass by value rather than by reference:
The above would create an offset and limit property on the component that are initialized to whatever index and size are, NOT cross-bind 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 instead of the attribute's value looked up in the parent scope (similar to pass by value).
To do this in can.stache, simply pass any value not wrapped in single brackets, and the scope property will be initialized to this string value:
The above will create a title property in the component's scope, which has a string
hello
. If instead hello was wrapped with brackets like{hello}
, a hello property would be looked up in the parent's scope.To do this in can.mustache, pass a value like in
can.stache
, and set the corresponding scope property in the component to@
. For example:With source HTML like:
Results in:
In 3.0,
can.mustache
syntax (requiring"@"
) will change tocan.stache
's (not requiring"@"
).If the tag's
title
attribute is changed, it updates the scope 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 scope from events within the template
Using html attributes like
can-EVENT-METHOD
, you can directly call a scope method from a template. For example, we can make<my-paginate>
elements include a next button that calls the scope'snext
method like:Scope methods get called back with the current context, the element that you are listening to and the event that triggered the callback.