can-stache
Version:
Live binding handlebars templates
136 lines (106 loc) • 3.87 kB
Markdown
for bidirectional value conversion.
can-stache.static
`stache.addConverter(converterName, getterSetter)`
Creates a helper that can do two-way conversion between two
values. This is especially useful with
[can-stache-bindings.twoWay two-way bindings] like:
```html
<input value:bind='stringToNumber(age)'/>
```
A converter helper provides:
- a `get` method that returns the value
of the `left` value given the arguments passed on the `right`.
- a `set` method that updates one or multiple of the `right` arguments
computes given a new `left` value.
`stringToNumber` might convert a number (`age`)
to a string (`value`), and the string (`value`) to a number (`age`)
as follows:
```js
import {stache, Reflect as canReflect, ObservableObject} from "can";
stache.registerConverter( "stringToNumber", {
get( numberObservable ) {
return "" + canReflect.getValue(numberObservable);
},
set( string, numberObservable ) {
canReflect.setValue(numberObservable, +string);
}
} );
var data = new ObservableObject({age: 36});
var frag = stache(`<input value:bind="age"/> Age: {{age}}`)(data);
document.body.append(frag);
```
{String|Object} converterName The name of the converter helper or an object to register multiple converters at once.
{can-stache.getterSetter} getterSetter An object containing get() and set() functions.
## Use
> __NOTE__: Before creating your own converter, you may want to look at what’s provided by [can-stache-converters].
These helpers are useful for avoiding creating [can-observable-object] getters and setters that do similar conversions on the component. Instead,
a converter can keep your components more ignorant of the demands of the
view. Especially as the view’s most common demand is that everything
must be converted to a string.
That being said, the following is a richer example of a converter,
but one that should probably be part of a view model.
```html
<input value:bind='hoursAndMinutes(hours, minutes)'/>
```
The following converts both ways `hours` and `minutes` to `value`.
```js
import {stache, ObservableObject, queues, Reflect as canReflect} from "can";
stache.addConverter( "hoursAndMinutes", {
get: function( hours, minutes ) {
return ""+canReflect.getValue( hours ) +":"+ canReflect.getValue( minutes );
},
set: function( newFullName, hours, minutes ) {
queues.batch.start();
const parts = newFullName.split( ":" );
canReflect.setValue( hours , +parts[0] );
canReflect.setValue( minutes , +parts[1] );
queues.batch.stop();
}
} );
var data = new ObservableObject({hours: 3, minutes: 17});
var frag = stache(`
<input value:bind="hoursAndMinutes(hours, minutes)"/>
Hours: {{hours}}, Minutes: {{minutes}}`
)(data);
document.body.append(frag);
```
It is possible to add multiple converters at once by passing an object instead of a string to the `name` argument:
```js
import {stache, ObservableObject, queues, Reflect as canReflect} from "can";
stache.addConverter({
"numberToHex": {
get: function(val) {
return canReflect.getValue(val).toString(16);
},
set: function(val, valCompute) {
return canReflect.setValue(valCompute, parseInt("0x" + val));
}
},
"capitalize": {
get: function(val){
return canReflect.getValue(val).toString().toUpperCase();
},
set: function(val, valCompute) {
return canReflect.setValue(valCompute, val.toLowerCase());
}
}
});
var data = new ObservableObject({fname: "Cherif", age: 36});
var frag = stache(`
<div>
<input value:bind="capitalize(fname)"/>
Firstname: {{fname}}
</div>
<div>
<input value:bind="numberToHex(age)"/>
Age: {{age}}
</div>
`
)(data);
document.body.append(frag);
```
can-stache.addConverter addConverter
Register a helper