I have a kendo Obervable as follows:
var ViewModel = kendo.observable({
ID: 1,
TITLE: "SomeValue",
});
and then I have bound this as follows:
kendo.bind($(".bind-view"), ViewModel );
Now there is button on the page. When clicked I need to check if there are any changes to this ViewModel.
I have tried
$(".ClearAnalysisInfo").on('click', function (event) {
ViewModel.bind("change", function (e) {
//Some code
});
});
But I'm not able to get this ViewModel property whether it changed or not.
Binding the ObservableObject's change event of inside the button's click handler is too late. You need to do that immediately after the ObservableObject is created.
Inside the change handler, you will receive information about the changed field. Use this information to raise some JavaScript flag or save the details you need, so that you can use them later in the button's click handler.
var viewModelChanged = false;
var ViewModel = kendo.observable({
ID: 1,
TITLE: "SomeValue",
});
ViewModel.bind("change", function (e) {
viewModelChanged = true;
});
$(".ClearAnalysisInfo").on('click', function (event) {
if (viewModelChanged) {
// ...
}
});
Related
I have an MVC Control for a KendoUI ComboBox that does NOT setup the Change Event ahead of time. Upon rendering, a page controller sets-up & shims-in its' own Change Event.
Oddly, this event gets called TWICE:
When I change the Selected Item
When I click away from the control
Q: What am I doing wrong?
Q: Is this HOW we should over-write the change event on an existing Kendo ComboBox?
MVC CONTROL:
As you can see, I am NOT defining any client-side events here...
#(Html.Kendo().ComboBox()
.Name("ddlTechnician")
.Filter("contains")
.Placeholder("Select Technician...")
.DataTextField("Text")
.DataValueField("Value")
.BindTo(new List<SelectListItem>() {
new SelectListItem() { Text = "Frank", Value = "1" },
new SelectListItem() { Text = "Suzie", Value = "2" },
new SelectListItem() { Text = "Ralph", Value = "3" }
})
.Suggest(true)
.HtmlAttributes(new { style = "width:300px;" }))
PAGE CONTROLLER:
And, I am only defining the event ONCE here. I have also confirmed the event isn't already firing BEFORE setting it in the Page Controller
$(document).ready(function () {
var PageController = (function ($) {
function PageController(options) {
var that = this,
empty = {},
dictionary = {
elements: {
form: null
},
instances: {
ddlTechnician: null
},
selectors: {
form: 'form',
ddlTechnician: '#ddlTechnician'
}
};
var initialize = function (options) {
that.settings = $.extend(empty, $.isPlainObject(options) ? options : empty);
dictionary.elements.form = $(dictionary.selectors.form);
// Objects
dictionary.instances.ddlTechnician = $(dictionary.selectors.ddlTechnician, dictionary.elements.form).data('kendoComboBox');
// Events
dictionary.instances.ddlTechnician.setOptions({ change: that.on.change.kendoComboBox });
};
this.settings = null;
this.on = {
change: {
kendoComboBox: function (e) {
// This is getting called MULTIPLE TIMES
console.log('kendoComboBox RAN');
}
}
}
};
initialize(options);
}
return PageController;
})(jQuery);
var pageController = new PageController({});
});
I was able to reproduce your problem on a Kendo JQuery Combobox when I set the event handler through setOptions, which is not the recommended way after the widget has been rendered. Instead you should use the "bind" method as shown in the documentation's example for change events.
Try changing the line of code where you set your event handler to this:
dictionary.instances.ddlTechnician.bind("change", that.on.change.kendoComboBox);
Here's a dojo that shows the difference: http://dojo.telerik.com/iyEQe
Hope this helps.
I have a template with helpers and events like:
Template.myTemplate.helpers({
edit: function () {
console.log('helper');
return this.value;
}
});
Template.myTemplate.events({
'click .edit_button': function () {
console.log('click');
// Toggle the value this.value
}
});
Through the logs (simplified here) I can verify that the helper is called when the template is rendered on the page. However, when the event is fired the helper console message is not fired. It as though the event changing the value does not trigger processing of the helper, making the page not very reactive.
I have tried to assign a reactive variable and use it, to no avail.
Template.myTemplate.rendered = function () {
this.value = new ReactiveVar();
}
// Setting and getting using the .get()/.set() methods.
How does one cause the helpers to be reprocessed from an event?
In events you want to set value to ReactiveVar object.
In helpers you simply return that value of this object, helpers behaves like Tracker.autorun, they are reactive.
Template.myTemplate.helpers({
edit: function () {
console.log('helper');
// helpers are wrapped with Tracker.autorun, so any ReactiveVar.get()
// inside this function will cause to rerun it
return Template.instance().value.get()
}
});
Template.myTemplate.events({
'click .edit_button': function (e, tmpl) {
console.log('click');
// here you save value
tmpl.value.set(newValue)
}
});
Template.myTemplate.created = function () {
this.value = new ReactiveVar();
}
I'm using require.js with backbone.js to structure my app. In one of my views:
define(['backbone', 'models/message', 'text!templates/message-send.html'], function (Backbone, Message, messageSendTemplate) {
var MessageSendView = Backbone.View.extend({
el: $('#send-message'),
template: _.template(messageSendTemplate),
events: {
"click #send": "sendMessage",
"keypress #field": "sendMessageOnEnter",
},
initialize: function () {
_.bindAll(this,'render', 'sendMessage', 'sendMessageOnEnter');
this.render();
},
render: function () {
this.$el.html(this.template);
this.delegateEvents();
return this;
},
sendMessage: function () {
var Message = Message.extend({
noIoBind: true
});
var attrs = {
message: this.$('#field').val(),
username: this.$('#username').text()
};
var message = new Message(attrs);
message.save();
/*
socket.emit('message:create', {
message: this.$('#field').val(),
username: this.$('#username').text()
});
*/
this.$('#field').val("");
},
sendMessageOnEnter: function (e) {
if (e.keyCode == 13) {
this.sendMessage();
}
}
});
return MessageSendView;
});
When keypress event is triggered by jquery and sendMessage function is called - for some reason Message model is undefined, although when this view is first loaded by require.js it is available. Any hints?
Thanks
Please see my inline comments:
sendMessage: function () {
// first you declare a Message object, default to undefined
// then you refrence to a Message variable from the function scope, which will in turn reference to your Message variable defined in step 1
// then you call extend method of this referenced Message variable which is currently undefined, so you see the point
var Message = Message.extend({
noIoBind: true
});
// to correct, you can rename Message to other name, e.g.
var MessageNoIOBind = Message.extend ...
...
},
My guess is that you've bound sendMessageOnEnter as a keypress event handler somewhere else in your code. By doing this, you will change the context of this upon the bound event handler's function being called. Basically, when you call this.sendMessage(), this is no longer your MessageSendView object, it's more than likely the jQuery element you've bound the keypress event to. Since you're using jQuery, you could more than likely solve this by using $.proxy to bind your sendMessageOnEnter function to the correct context. Something like: (note - this was not tested at all)
var view = new MessageSendView();
$('input').keypress(function() {
$.proxy(view.sendMessageOnEnter, view);
});
I hope this helps, here is a bit more reading for you. Happy coding!
Binding Scopes in JavaScript
$.proxy
I'm having a problem with the click events not working using a Javascript MVC Controller.
TEST.Assignments.AssignmentsController = function (element) {
var elements = {
activeAssignmentsPanel: $('#lpn-activeAssignments_Cont'),
assignmentViewLink: $("#lpn-activeAssignments_Cont table tr th a")
};
var _this = this;
var model = new TEST.Assignments.AssignmentModel();
this.buildAssignmentsList = function () {
var assignments = model.getActiveAssignmentsList({
assignmentMode: "active",
mock: true,
success: function (data) {
dust.render("ActiveAssignmentsPanel", data, function(err, out) {
elements.activeAssignmentsPanel.append(out);
});
}
});
};
this.getAssignmentDetails = function(assignmentId) {
console.log(assignmentId);
};
//bind all events
elements.assignmentViewLink.click(function (e) {
console.log("blah");
console.log($(this).data("assignmentKey"));
});
};//end assignments controller
$(function () {
var assignmentsController = new TEST.Assignments.AssignmentsController();
assignmentsController.buildAssignmentsList();
});
If you look at the //bind events, I have a click function there that should be working. But it is not. The constructor is being called and the elements are traced out correctly. Any idea why the click event won't work?
I assume the assignmentViewLink elements are created and appended in the success callback. If so, it looks like a sequence problem. When you bind the click event, the assignmentViewLink elements have not been created yet, and hence, the click eventhandler isn't attached.
//bind all events
// assignmentViewLink is empty []
elements.assignmentViewLink.click(function (e) {
console.log("blah");
console.log($(this).data("assignmentKey"));
});
To verify this, move the elements.assignmentViewLink(...) into the success callback.
I've written a program that includes a form that the user interacts with. Because there are lots of events bound to different buttons I have written a loop that parses some JS that contains the form input information. Here is some example data:
var value = 0,
forms = {
place_controls : {
attrs : {
'class' : 'place-form'
},
input : {
place_x : {
attrs : {
type : 'text',
},
events : {
change : function () {
value = 10;
}
}
},
place_y : {
attrs : {
type : 'text',
},
events : {
change : function () {
value = 50
}
}
}
}
}
}
The data is then parsed by this:
$.each(forms, function (form_index, form) {
var $form_markup = $('<form>').attr(form.attrs);
// Next: loop through each input element of the form we've reached
$.each(form.input, function (element_index, element) {
var $elem = $('<input>').attr(element.attrs);
$elem.appendTo($form_markup);
if (element.events !== undefined) {
$.each(element.events, function (event_index, event) {
$elem.bind(event_index, event);
//$form_markup.on(event_index, $elem, event);
});
}
});
$form_markup.appendTo($form_goes_here);
});
As you can see, I'm using .bind() at the moment, however I want to use .on(). Unfortunately, when I do this all of the items within a form are bound to the last event parsed by the function. When I use .bind() everything works as planned - i.e. Clicking on 'place_x' sets value to 10, clicking 'place_y' sets value to 50.
When using .on(), whichever I change sets value to 50, which I am assuming is because the last function is becoming bound to each event.
Can anybody see what I have done wrong?
Update: There are many different ways to do this, and I have subsequently changed how my code works, however this question is related to why .bind() is working and why .on() is not.
//$elem.bind(event_index, event);
//It looks like you should just be using .on() like this
$elem.on(event_index, event);
The way it looks like you are trying to use .on() is in the live -bubbling- event sort of way, it looks like only the last event you are created is sticking, why each value just gets set to 50.
//$form_markup.on(event_index, $elem, event);
You can create elements with property maps that include handler functions in one simple call:
var $elem = $('<input/>', properties);
The "properties" object can contain event handlers:
var $elem = $('<input/>', {
type: 'text',
name: 'somethingUseful',
click: function(ev) { /* click handler */ },
change: function(ev) { /* change handler */ },
css: { color: "red" }
});