I want to implement simple toggle button functionality using Ractivejs. Here is the code:
function MyViewModel(model) {
var self = this;
self.value = false;
self.toggleValue = function () {
self.value = !self.value; //this will probably not update view, but it is not the point here
};
}
var viewModel = new MyViewModel(model);
var ractive = new Ractive({ el: 'mydiv', template: '#mytemplate', data: viewModel });
and here is my template
<script id='mytemplate' type='text/ractive'>
<p>Value: {{value}}</p>
<button type="button">Toggle</button>
</script>
How do I call MyViewModel.toggleValue function when the button is clicked? For now I know two options:
on-click='toggle("value")'
to button
element. However, let's assume that my toggleValue function may be somewhat more complicated, so this solution is not enough.I can add on-click='toggleValue'
to button
element. But then I need to add this code:
ractive.on('toggleValue', function () { viewModel.toggleValue(); });
which means that:
toggleValue
is global for Ractive instance and not view model specific which means maintenance issues sooner or later.$("button").click(myFunction)
.So how do I do it correctly? I need equivalent of KnockoutJs' data-bind="click: toggleValue"
.
EDIT: For working code have a look here: http://jsfiddle.net/xak5k8rd/
You could create that type of syntax by adding a prototype method to Ractive:
Ractive.prototype.bind = function(context, method){
// if using < 0.6.1 you may encounter bug {{this}} or {{.}} not returning model root
//context = context || this.data
context[method].call(context, this)
}
then consume in your template as:
<button type="button" on-click="bind(this, 'toggleValue')">Toggle</button>
<ul>
{{#tab}}
<li on-click="bind(this, 'click')">{{val}}</li>
{{/tab}}
</ul>
See http://jsfiddle.net/obdk4k2o/2/
EDITED: Added context to bind function. Note any template model value could be passed, but this
is certainly handy for lists.
EDITED: In 0.6.1
, method calls have access to this.event
meaning the keypath is available as well as the context (so it doesn't need to be passed in).
The method becomes:
Ractive.prototype.bind = function(method){
var context = this.event.context,
keypath = this.event.keypath
context[method].call(context, this, keypath)
}
Template is:
<button type="button" on-click="bind('toggleValue')">Toggle</button>
<ul>
{{#tab}}
<li on-click="bind('click')">{{val}}</li>
{{/tab}}
</ul>
And in your viewmodel:
self.click=function(ractive, keypath){
ractive.set(keypath + ".val", !self.val);
alert('click');
}