knockout kendo events fires twice - javascript

Hej, I have a problem here with the knockout-kendo framework.
Every event gets fired twice. Can someone tell me whats wrong with my code?
I created a small fiddle.
var StoreViewModel = function () {
var self = this;
this.stores = ko.observableArray(stores);
this.selectedStore = ko.observable(stores[0].Id);
// this event fires twice, dont know why!
this.dataBoundEvent = function () {
alert('databound event ...');
//doSomething();
};
this.changeEvent = function () {
alert('change event ...');
//doSomething();
};
};
Thanks!

The binding event is called when the grid is initialize and when the data is set.
To stop this, just use dataSource instead of data
<div id="wrapper">
<select data-bind="kendoDropDownList: {
dataSource: stores,
dataTextField: 'Address',
dataValueField: 'Id',
dataBound: dataBoundEvent,
change: changeEvent
}"></select>
</div>
dataSource is the normal way and the supported way of kendo.

I believe dataBoundEvent is being called for
Binding the backing data (stores)
Binding the selected value (selectedStore)

Related

handle dojo EdgeToEdgeStoreList event

I create an EdgeToEdgeStoreList from dojox/mobile as follow:
<ul id="listCustomers"></ul>
storeCustomers = new Memory({data: data, idProperty: "label"});
var listCustomers = new EdgeToEdgeStoreList({
select: "single",
store: storeCustomers
}, "listCustomers");
listCustomers.startup();
then I want to handle the onCheckStateChanged event:
var listCustomers = dom.byId("listCustomers");
on(listCustomers, "checkStateChanged", function (listItem, newState) {
console.log(listItem, newState);
});
but this never fires.
What is the correct method?
It's ok also a way to get an array of selected items (just one in my specific case, of course).
There are two ways to do this, either use the listitems onclick, or if you want to use checkStateChanged you have to add that listener Widget.
var listCustomers = dijit.registry.byId("listCustomers");
on(listCustomers, "checkStateChanged", function (listItem, newState) {
console.log(listItem, newState);
});

How to trigger ready event on JQuery chosen plugin?

I am trying to bind an liszt:ready event of my list, to be invoked once that the list has been initialized by chosen.
I follow the steps that here are describing without any success.
This is my code:
var initPreferredCollaboratorChosen = function () {
$("#preferredCollaboratorChosenId").chosen({width: "95%"}).trigger("chosen:ready");
};
var initListener = function () {
$("preferredCollaboratorChosenId").on("chosen:ready", function(){
alert("Hey, I am ready!");
});
initPreferredCollaboratorChosen()
};
I try with "liszt:ready" instead "chosen:ready" as well.
Can anyone that has work with this plugin tell me how make it?.
Regards.

KnockoutJS select fires onChange after setting default value

I have set up the following select for changing semesters on page. When the select detects a change, the changeSemesters function is fired, which runs an AJAX that replaces the current data on the page with data specific to the selected semester.
View
<select data-bind="options: semestersArr, optionsText: 'name', optionsValue: 'id', value: selectedSemester, event: { change: changeSemesters }"></select>
ViewModel
this.selectedSemester = ko.observable();
//runs on page load
var getSemesters = function() {
var self = this, current;
return $.get('api/semesters', function(data) {
self.semestersArr(ko.utils.arrayMap(data.semesters, function(semester) {
if (semester.current) current = semester.id;
return new Model.Semester(semester);
}));
self.selectedSemester(current);
});
};
var changeSemesters = function() {
// run ajax to get new data
};
The problem is that the change event in the select fires the changeSemester function when the page loads and sets the default value. Is there a way to avoid that without the use of a button?
Generally what you want to do in these scenarios is to use a manual subscription, so that you can react to the observable changing rather than the change event. Observables will only notify when their value actually changes.
So, you would do:
this.selectedSemester.subscribe(changeSemesters, this);
If selectedSemester is still changing as a result of getting bound, then you can initialize it to the default value.
this.selectedSemester = ko.observable(someDefaultValue);

Can't modify CustomEvent data

I need to fire a custom event each time when clicked on div with different data attached.
Here is a simplified variant of my code (JSFiddle):
<div onclick="selectItem(Math.random())">click me</div>
<script>
function selectItem(id) {
var event_data = {
myid: id
};
if (!arguments.callee.event)
arguments.callee.event = new CustomEvent("selectItem", {detail: event_data});
arguments.callee.event.detail = event_data; // no success here
document.dispatchEvent(arguments.callee.event);
}
document.addEventListener("selectItem", function(event) {
console.log(event.detail); // same thing all the time :(
});
</script>
But in the event listener function I receive the same data each time the event is fired. I tried to change the event before dispatchEvent but seems it is read only object.
Is there any other options to send different data each time i click on div?
The reason is that detail property of the event can be any object but they are read only, i.e they can be set only when the event is created.Iit is specifically used to provide details regarding the event, and not for attaching data for each dispatch of the event.
interface CustomEvent {
readonly attribute any detail;
};
Probably you can just set a custom property data to the event during each dispatch and access that property.
Try:
function selectItem(id) {
var event_data = {
myid: id
};
if (!arguments.callee.event) arguments.callee.event = new CustomEvent("selectItem");;
arguments.callee.event.data = event_data;
document.dispatchEvent(arguments.callee.event);
}
document.addEventListener("selectItem", function(event) {
console.log(event.data);
});
Fiddle
Or you would need to init the custom Event each time to set the details property like this:
arguments.callee.event.initCustomEvent("selectItem", true, true, event_data);
and details property will have new updated value each time the event is dispacthed.
Demo

How can I append an attribute to a JavaScript event?

At row level I catch the event and try to add an extra parameter
onRowClick: function(e){
console.log("Event in row");
e.model = "test";
console.log(e.model) // prints 'test'
}
In main view I catch the same event again
onRowClick: function(e){
console.log("Event in main view");
console.log(e.model) //prints undefined
}
Console:
>Event in row
>test
>Event in main view
>undefined
How can I append an attribute to the event?
The answer is that you don't catch the same event, but rather two (initially) identical events. Changing the first does not change the latter.
If you want to pass data between those events, you would need to store that data elsewhere (e.g. a closure, or if you don't care about the scope save it in the window object).
There are 2 ways that I know of to pass data to a jQuery event. One with with e.data, you can add any properties to e.data like this.
http://www.barneyb.com/barneyblog/2009/04/10/jquery-bind-data/
the other way is to use closures such as:
function myFunc() {
var model = 'test';
var x = {
onRowClick: function(e){
console.log("Event in row");
console.log(model) // prints 'test'
}
}
}
instead of catching the rowClick event in the main view, i suggest you catch it in the row view, and pass it through the backbone event system...
your parentview can bind to it's rows to catch a click.
there are two ways to do this,
trigger a custom event on your row's model, and let the parent bind to every model in the collection, though that seems like a hack and a performance hit.
i suggest doing it with an event aggregator:
var App = {
events: _.extend({}, Backbone.Events);
};
var myGeneralView = Backbone.Views.extend({
initialize: function() {
_.bindAll(this, "catchMyCustomEvent";
/*
and here you bind to that event on the event aggregator and
tell it to execute your custom made function when it is triggered.
You can name it any way you want, you can namespace
custom events with a prefix and a ':'.
*/
App.events.bind('rowView:rowClicked');
},
catchMyCustomEvent: function (model, e) {
alert("this is the model that was clicked: " + model.get("myproperty"));
}
// other methods you will probably have here...
});
var myRowView = Backbone.Views.extend({
tagName: "li",
className: "document-row",
events: {
"click" : "myRowClicked"
},
initialize: function() {
_.bindAll(this, "myRowClicked");
},
myRowClicked: function (e) {
/*
You pass your model and your event to the event aggregator
*/
App.events.trigger('rowView:rowClicked', this.model, e);
}
});

Categories