Kendo-Knockout: Cannot call a function within template - javascript

I want to call the onHover function but with no suceess. The only way I managed to do this is if the function is global, but this is no what I need.
What I am trying to do is onMouseOver of some element of the dropdown to take its value and do something with it in my viewmodel.
HTML:
<div>
<div data-bind="with: myInnerViewModel">
<input type="text" data-bind="kendoDropDownList: {data: myData, value: myValue,template:'<span onMouseOver = \'onHover(this)\' title=\'${data}\'>${data}</span>'}" />
<div>
</div>
JS:
var myViewModel = function () {
this.myInnerViewModel = {
myData : [1, 2 , 3],
myValue : ko.observable(1),
onHover : function(e){
alert(1);
}
};
};
ko.applyBindings(new myViewModel());
fiddler: http://jsfiddle.net/QZWPR/30/

The issue lies with location of your function. If you were to change
onMouseOver = \'onHover(this)\'
to
onMouseOver = \'myViewModel.myInnerViewModel.onHover(this)\'
then i expect you would see your alert.
OR
you need to use the event binding on your span
<span data-bind="event: { mouseover: onHover}">

Related

KnockOutJS Show Hide elements on dropdown selection change

Hi I am trying to get selected value of dropdown in Knockout js so that I can hide/ show other elements based on selection. Below is what I have tried.
What is happening that I am able to get right value on button click but not on dropdown selection change.
Below is my code. The button gives right value, but dropdown selection change event gives previous value & not the selected one.
JS
function ViewModel() {
var self = this;
self.optionValues= ko.observableArray(["Test1", "Test2", "Test3"]);
self.selectedValue = ko.observable();
self.save = function() {
alert(self.selectedValue());
}
}
ko.applyBindings(new ViewModel());
HTML
<select data-bind="event:{ change: save},options: optionValues, value: selectedValue"></select>
<button data-bind="click: save">Save</button>
Instead of the change event binding binding, you should subscribe directly on your selectedValue observable, and call your logic from there:
function ViewModel() {
var self = this;
self.optionValues = ko.observableArray(["Test1", "Test2", "Test3"]);
self.selectedValue = ko.observable();
self.selectedValue.subscribe(function(newValue) {
self.save();
});
self.save = function() {
alert(self.selectedValue());
}
}
ko.applyBindings(new ViewModel());
Html:
<select data-bind="options: optionValues, value: selectedValue"></select>
<button data-bind="click: save">Save</button>
Demo JSFiddle.

KnockoutJs doesn't react to custom events

I'm binding my ViewModel's isChecked property to a data-whatever attribute. The value of this attribute is changed by jQuery:
$element.data('whatever', "true")
KnockoutJs doesn't notice this change and my ViewModel's property doesn't change. How can I make KnockoutJs notice it?
I tried something like that, but it didn't work:
JavaScript "view layer" script:
$element.data('whatever', "true")
$element.trigger("myCustomEvent")
The view:
<div data-bind="attr: { 'data-whatever': isChecked, event : {myCustomEvent: checkedFunction} }">
checkedFunction is just an empty method in the ViewModel to fit the event binding syntax. It still looks like KnockoutJs is not listening to myCustomEvent.
EDIT
As Fisherman suggested I used $element.attr instead of $element.data, but it still doesn't work:
<html>
<div id="test" data-bind="attr: { 'data-whatever': isChecked }">my div</div>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<script>
var vm = {
isChecked : ko.observable("one"),
};
$(function () {
ko.applyBindings(vm);
console.log($('#test').attr('data-whatever')); // "one"
$('#test').attr('data-whatever', 'two');
console.log($('#test').attr('data-whatever')); // "two"
console.log(vm.isChecked()); // // "one" again, thouh it should be "two"
});
</script>
</html>
even if I add the event:
<html>
<div id="test" data-bind="attr: { 'data-whatever': isChecked, event :{ myCustomEvent : aFunction }}">my div</div>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<script>
var vm = {
isChecked : ko.observable("one"),
aFunction : function(){ }
};
vm.isChecked.subscribe(function(){
console.log("hit the event"); // never happens
});
$(function () {
ko.applyBindings(vm);
console.log($('#test').attr('data-whatever')); // "one"
$('#test').attr('data-whatever', 'two');
$('#test').trigger('myCustomEvent');
console.log($('#test').attr('data-whatever')); // "two"
console.log(vm.isChecked()); // "one" again, though should be "two"
});
</script>
</html>
You can't set the data attribute with jQuery's data() functions. Have a look at the documentation: http://api.jquery.com/data/
The data- attributes are pulled in the first time the data property is
accessed and then are no longer accessed or mutated (all data values
are then stored internally in jQuery)
http://jsfiddle.net/prpL0x3j/
console.log($('#test').data('whatever'));
// one
$('#test').data('whatever', 'two');
console.log($('#test').data('whatever'));
// two
Check out the attribute of the DOM element in the developer bar - it does not change, even though jQuery's data value changed.
Consider using the attr() function: http://api.jquery.com/attr/
$element.attr('data-whatever', "true")

Meteor class being fired multiple times from JQuery.click()

I have a generic template that I use multiple times.
{{#each item}}
{{> genericTemplate}}
{{/each}}
Inside of this template I have a button that when it is clicked fires a hidden file input in the generic template.
$(".upload").click();
Unfortunately for each template the ".upload" class gets fired. So if I had four items, it would give me 4 file inputs. I can't give the buttons a unique id="" because then I would have to explicitly define each event for each id, negating the entire reason for creating the generic template in the first place. What is the proper way to achieve something like this?
EDIT:
My template events look like this:
Template.generic.events({
'click .fileUpload' : function () {
$(".upload").click(); // sets off the 4 templates .upload class
},
'change .upload' : function (e) {
console.log('upload')
}
})
HTML:
<template name="generic">
<!--Hidden Inputs that get fired on click events -->
<div class="hiddenFile">
<input type="file" class="upload"/>
</div>
<button class="btn btn-success fileUpload">UPLOAD FILE </button>
</template>
Try this trick :
Template.generic.events({
'click .fileUpload' : function (event,template) {
// fires only the template instance .upload
template.$(".upload").click();
},
'change .upload' : function (e) {
console.log('upload')
}
});
You can use Template.instance to fire the event in only the appropriate instance:
'click .fileUpload' : function () {
var template = Template.instance();
template.$(".upload").click(); // should only set off this specific upload input.
}
That said, is there really no way you can achieve the same effect without manufacturing an event in the DOM? It's up to you, but can't you just run the code that's going to replace console.log('upload') directly?
Maybe smth like this?
Template.generic.events({
'click .fileUpload' : function (event, target) {
e.currentTarget.parent().find(".upload").click(); // sets off the 4 templates .upload class
},
'change .upload' : function (e) {
console.log('upload')
}
})

Passing value to a function with knockout

I use knockout here on a very basic example where I would like to pass the value of the clicked item to the function. I tried something which doesn't work. Does someone can show me how to proceed? Maybe I'm doint the wrong way?
Thanks for your help.
<div class='liveExample'>
<h2 data-bind="value: 'A', click: myFunction">Aaaaa</h2>
<h2 data-bind="value: 'B', click: myFunction">Bbbbb</h2>
<h2 data-bind="value: 'C', click: myFunction">Ccccc</h2>
</div>
// Here's my data model
var ViewModel = function() {
this.myFunction = function (elm)
{
alert('you clicked: ' + elm);
}
};
ko.applyBindings(new ViewModel()); // This makes Knockout get to work
jsFiddle here: http://jsfiddle.net/LkqTU/10229/
PS: I know we can do ...click: function () { myFunction('A'); }"> but I think there is a better way.
You can get value from event target (which is h2 element):
// Here's my data model
var ViewModel = function() {
this.myFunction = function (data, event)
{
debugger;
alert('you clicked: ' + event.target.value);
}
};
ko.applyBindings(new ViewModel());
Read more on click binding
Try:
this.myFunction = function (vm, event)
{
alert('you clicked: ' + event.srcElement);
}
this.myFunction = function (val1, val2)
{
...;
}
and in binding you must to set:
<h2 data-bind="value: 'C', click: myFunction.bind($data, 'A', 'B')">Ccccc</h2>
This must help you. You can pass any count of values by this method.

Backbone.js: capture custom events on jQuery plugin?

I have a Backbone view for a search form. The form includes several elements, including a slider implemented in jSlider. I want to capture all changes to the form, and update the results shown accordingly.
I can capture the click events fine, but I don't know how to capture the slide event on jSlider - I know how to bind custom events in Backbone, but jSlider seems not to have a way to bind it directly.
Here's my HTML:
<form id="searchform">
<input type="text" id="city" />
<input type="text" id="type" />
<input id="price-jslider" type="slider" name="price" value="1;500" />
</form>
And here's my Backbone code:
var SearchFormView = Backbone.View.extend({
el: $('#searchForm'),
events: {
"click input": "updateResults",
// how to capture slide event on jslider?
},
updateResults: function(e) {
// do stuff
}
});
Does anyone have any ideas on how to capture this sort of event?
You can pass an onstatechange function when initializing the jQuery slider:
var SearchFormView = Backbone.View.extend({
el: $('#searchForm'),
render: function() {
var self = this;
$("#price-jslider").slider({
onstatechange: function( value ) {
self.updateResults();
}
});
},
events: {
"click input": "updateResults"
},
updateResults: function(e) {
// do stuff
}
});
from jslider page
onstatechange function(value)
Function fires while slider change state.
callback function(value)
Function fires on "mouseup" event.
when you instantiate jslider, you define those function in option
$(whatever).jslider({
onstatechange : function(v) {
//set your input value to v
$('#searchForm').trigger('click')
}
})

Categories