Cause helper to react to event - javascript

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();
}

Related

How to make this jquery code fire the function itself instead of binding to a button to fire the function?

How to make this jquery code fire the function itself instead of binding to a button to fire the function?
self.ShowWindow= { observable: ko.observable(false) };
self.OnToggleShowWindow = (it) => () => it.observable(!it.observable());
$('#showWindowButton').click(self.OnToggleShowWindow (self.ShowWindow));
Right now I have to create a button and bind it with my code to be able to trigger a function in my react component. What I'm wondering is that, is it possible to just trigger the function without halving to trigger the jquery click?
My ViewModel in the javascript component.
$ViewModel = function (element) {
var self = this;
self.ShowWindow= { observable: ko.observable(false) };
self.OnToggleShowWindow = (it) => () => it.observable(!it.observable());
self.OnToggleShowWindow (self.ShowWindow);
$(document).ready(function () {
self.OnToggleShowWindow(self.ShowWindow)
};
self.ShowDialog = function (componentId, componentName) {
// The fucntion OnToggleShowWindow is supposed to be called here
};
}
Only outside the ShowDialog function is bound at rendering the page. After what the showdialog is just a function that updates on the already bounded observables.
In my react component I have subscribed to the function, which I now try to retrieve:
this.props.toggleShowWindow.observable.subscribe(this.onToggleShowWindow);
Put () after it instead of passing it to click.
$('#showWindowButton').click(self.OnToggleShowWindow (self.ShowWindow));
becomes:
self.OnToggleShowWindow(self.ShowWindow)()
Don't forget the () after it. Pay close attention to the above line of code and make sure you don't miss any () out.

Kendo Observable Change event

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) {
// ...
}
});

jQuery global/local event execution order

I have a panel widget with a button. Clicking the button should execute some global actions related to all such widgets and after that execute some local actions related to this widget instance only. Global actions are binded in a separate javascript file by CSS class like this:
var App = function ()
{
var handleWidgetButton = function ()
{
$('.widgetBtn').on('click', function (e)
{
// do smth global
});
return {
init: function ()
{
handleWidgetButton();
}
};
}
}();
jQuery(document).ready(function()
{
App.init();
});
And in the html file local script is like this:
$("#widgetBtn1234").click(function (e)
{
// do smth local
});
Currently local script is executed first and global only after while I want it to be the opposite. I tried to wrap local one also with document.ready and have it run after global but that doesn't seem to change the execution order. Is there any decent way to arrange global and local jQuery bindings to the same element?
The problem you're having comes from using jQuery's .ready() function to initialize App, while you seem to have no such wrapper in your local code. Try the following instead:
var App = function ()
{
var handleWidgetButton = function ()
{
$('.widgetBtn').on('click', function (e)
{
// do smth global
});
return {
init: function ()
{
handleWidgetButton();
}
};
}
}();
$(function()
{
App.init();
});
Then in your local JS:
$(function() {
$("#widgetBtn1234").click(function (e)
{
// do smth local
});
});
Note that $(function(){}) can be used as shorthand for $(document).ready(function(){});. Also, make sure your JS file is located before your local JS, as javascript runs sequentially.
Alternatively, you can use setTimeout() to ensure everything's loaded properly:
(function executeOnReady() {
setTimeout(function() {
// Set App.isInitialized = true in your App.init() function
if (App.isInitialized) runLocalJs();
// App.init() hasn't been called yet, so re-run this function
else executeOnReady();
}, 500);
})();
function runLocalJs() {
$("#widgetBtn1234").click(function (e)
{
// do smth local
});
};
How about this instead:
var widget = $("#widgetBtn1234").get(0);//get the vanilla dom element
var globalHandler = widget.onclick; //save old click handler
// clobber the old handler with a new handler, that calls the old handler when it's done
widget.onclick = function(e){
//do smth global by calling stored handler
globalHandler(e);
//afterward do smth local
};
There might be a more jqueryish way to write this, but I hope the concept works for you.
-------VVVV----keeping old answer for posterity----VVVV--------
Why not something like this?
var App = function ()
{
var handleWidgetButton = function ()
{
$('.widgetBtn').on('click', function (e)
{
// do smth global
if(this.id === 'widgetBtn1234'){
//do specific things for this one
}
});
return {
init: function ()
{
handleWidgetButton();
}
};
}
}();
Please excuse any syntax errors I might have made as I haven't actually tested this code.
Check out my simple JQ extension I created on jsbin.
http://jsbin.com/telofesevo/edit?js,console,output
It allows to call consequentially all defined personal click handlers after a global one, handle missed handlers case if necessary and easily reset all personal handlers.

When on enter keypress is triggered by jquery my model is undefined

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

Function becomes undefined after first trigger

I have a block of code like so:
function doSomething() {
someVar.on("event_name", function() {
$('#elementId').click(function(e) {
doSomething();
});
});
}
// and on document ready
$(function () {
$('#anotherElemId').click(function () {
doSomething();
});
});
The problem that I'm encountering is that when I call doSomething() from anotherElemId click event(that is binded on document ready) it works as expected, but calling it recursively from elementId click doesn't work.
Any ideas? Thinking is something trivial that I'm missing.
Is someVar an actual jQuery reference to a dom element? (e.g. $('#someitem'))
The second problem is you cant put a .click event inside a function that you would like to instantiate later on. If you are trying to only allow #elementId to have a click event AFTER some previous event, try testing if a tester variable is true:
var activated = false;
$(function () {
$('#anotherElemId').click(function () {
activated = true;
});
$('#secondElemId').on("event_name", function() {
if (activated) {
// code that happens only after #anotherElemId was clicked.
}
});
});

Categories

Resources