Avoid clicking twice to begin editing boolean (checkbox) cell in Backgrid - javascript

We are using Backgrid and have discovered that to begin editing a "boolean" (checkbox) cell in Backgrid, you must click twice: the first click is ignored and does not toggle the state of the checkbox. Ideally we would get to the root of what is causing this behavior (e.g. is preventDefault being called) and solve it there, but I at first I tried a different approach with the following extension of BooleanCell's enterEditMode method which seemed like a logical place since it was upon entering edit mode that the checkbox click was being ignored.
Problem is my attempt also toggles the state of the previously edited checkbox. Here is the code.
var BooleanCell = Backgrid.BooleanCell.extend({
/*
* see https://github.com/wyuenho/backgrid/issues/557
*/
enterEditMode: function () {
Backgrid.BooleanCell.prototype.enterEditMode.apply(this, arguments);
var checkbox = this.$('input');
checkbox.prop('checked', !checkbox.prop('checked'));
}
});

The following seems to work:
var BooleanCell = Backgrid.BooleanCell.extend({
editor: Backgrid.BooleanCellEditor.extend({
render: function () {
var model = this.model;
var columnName = this.column.get("name");
var val = this.formatter.fromRaw(model.get(columnName), model);
/*
* Toggle checked property since a click is what triggered enterEditMode
*/
this.$el.prop("checked", !val);
model.set(columnName, !val);
return this;
}
})
});
This is because the render method gets called by Backgrid.BooleanCell's enterEditMode method on click, and said method destroys and re-creates the checkbox as follows but in so doing loses the checked state (after the click) of the original "non-edit-mode" checkbox
this.$el.empty();
this.$el.append(this.currentEditor.$el);
this.currentEditor.render();

A simpler approach:
var OneClickBooleanCell = Backgrid.BooleanCell.extend({
events: {
'change input': function(e) {
this.model.set(this.column.get('name'), e.target.checked);
},
},
});
This bypasses the CellEditor mechanism entirely and just reacts to the input event on the checkbox by updating the model.

Related

Kendo toolbar button not firing click event after being enabled

This is my logic, here I am trying to disable the save changes button and prevent click event on it if the user enters a duplicate value and enable it again if the user changes the values but after enabling it the update / save event does not occur am I doing something wrong? This is my code
function OnChange(data) {
//data.preventDefault();
$(".k-grid-save-changes")
.attr("role", "button")
.removeClass("k-state-disabled")
//.addClass("k-grid-save-changes")
.click(function () {
return true;
});
//console.log("data", data.items["0"].ProviderTypeName);
var name = data.items["0"].ProviderTypeName;
var Id = data.items["0"].Id;
var grid = $("#grid").data("kendoGrid");
//console.log("Grid ", grid);
grid.tbody.find('>tr').each(
function () {
$(this).css('background', 'white');
var dataItem = grid.dataItem(this);
//console.log(dataItem.ProviderTypeName)
if (dataItem.ProviderTypeName == name && dataItem.Id != Id) {
$(this).css('background', 'red');
$(".k-grid-save-changes")
//.removeClass("k-grid-save-changes")
.addClass("k-state-disabled")
//.removeAttr("role")
.click(function () {
return false;
});
}
});
}
This is where is call the on change event
.Events(events => events.RequestStart("OnRequestStart").Change("OnChange").RequestEnd("OnRequestEnd").Error("onError"))
If I remove the "return false;" it is working as expected but this allows duplicated values to be saved. So I have used this.
If I understand correctly in your code you do exactly what you mention as a problem. At every change you disable the save functionality with the return false. You don't enable it again at any point.
If you add an event handler to the button then you have to undo it at a later point. Since though I don't believe that the validation should occur at the change event but at the button click I would suggest to use the grid Save event where you could iterate dataSource.data() of your grid (much better) do your check and if anything happens return false.
One other way to go since you probably want the css effect with the background is to keep your code and discard the click event. Just set a flag that you could use in the save event. Something like this:
if(// your control){
$(this).css('background', 'red');
duplicatedValue = true;
}else{
.removeClass("k-grid-save-changes");
duplicatedValue = false;
}
And in the save event
function onSave(){
if(duplicatedValue){
return false;
}
}

Selectize.js: onItemAdd event triggered when silently adding an item

Using Selectize.js, I'm trying to initialize the dynamically pre-select one of the item of the list without triggering the onItemAdd event. In the following code, the event is triggered even if the silent parameter is truthy:
$(function () {
$('select').selectize({
onItemAdd: function () {
alert("Add item");
}
});
// this triggers an the event
$('select')[0].selectize.addItem('2', true);
});
JSFiddle: http://jsfiddle.net/zuzat0dc/1/
According to the documentation:
addItem(value, silent): "Selects" an item. Adds it to the list at the current caret position. If "silent" is truthy, no change event will be fired on the original input.
Any idea how to avoid triggering the onItemAdd event? Is the silent parameter b0rked or should I use the change event instead?
A quick fix that worked for me was to keep a state flag and refer to it in the event handler...
$(function () {
var initialising = true;
$('select').selectize({
onItemAdd: function () {
if(!initialising) {
alert("Add item");
}
}
});
// this triggers an the event
$('select')[0].selectize.addItem('2', true);
initialising = false;
});
The silent parameter in addItem(value, silent) affects only to the fact whether or not the change event. You can't avoid item_add event with silent = true.
The only thing that worked for me was to store item_add event locally, remove it from selectize instance and set it back after I added the item:
onItemAdd: function(val) {
var e = this._events['item_add'];
delete this._events['item_add'];
this.addItem(123);
this._events['item_add'] = e;
}

Call back from styled radio buttons

I am using the jQuery plugin radiosToSlider (http://rubentd.com/radios-to-slider/) and need to make sure that all radio button groups are checked and to give an alert when they are
I can do this if they are just radio buttons by checking the length but because the plugin changes the input buttons I am having difficulties
My fiddle is
http://jsfiddle.net/yFaAj/270/
$(document).ready(function () {
$(".radios").radiosToSlider();
});
$(":radio").change(function () {
var names = {};
$(':radio').each(function () {
names[$(this).attr('name')] = true;
});
var count = 0;
$.each(names, function () {
count++;
});
if ($(':radio:checked').length === count) {
alert("all answered");
}
}).change();
thanks
The problem isn't that the plugin changes your structure (although it does add some ins elements, which I don't agree with), it's that the plugin doesn't fire a change event for the converted radio controls, and setting the checked property interactively doesn't appear to do so either.
Since the plugin author doesn't publish an API for this use case, it's hard to know whether this is by design or oversight, but the source code definitely doesn't fire the event when the slider is clicked:
this.bearer.find('.slider-level').click( function(){
var radioId = $(this).attr('data-radio');
slider.bearer.find('#' + radioId).prop('checked', true);
slider.setSlider();
});
Your options, as I see them:
Contact the API author and ask for a bug fix, or the intended way to support this case
Downside: Time: dependent on the author to respond
Attach your "check" function to the click event of the .slider-level class, as the API does.
Downside: Brittle: future versions of the plugin may attach the behavior to different selectors
Attach your function to the click event of your radio group, and catch click events on the bubble
Downside: Inefficient: It will check for every click in the radio control
Here's a sample implementation of option 3. DEMO.
$(document).ready(function () {
$(".radios").radiosToSlider();
});
var makeIsRadioGroupChecked = function(selector) {
var $radioGroup = $(selector);
return function isRadioGroupChecked() {
return $radioGroup.find(':checked').length > 0;
};
};
var isOptionsChecked = makeIsRadioGroupChecked('#optionsRadioGroup');
var isSizeChecked = makeIsRadioGroupChecked('#sizeRadioGroup');
var areAllGroupsChecked = function() {
return isOptionsChecked() && isSizeChecked();
};
var alertIfAllGroupsChecked = function() {
if (areAllGroupsChecked()) {
alert("all answered");
}
};
$('.radios').on('click', alertIfAllGroupsChecked);

Angular - Kendo treeview checkbox change event firing multiple times

I am trying to implement the checkbox change event using angular but seeing the event firing multiple times when a checkbox is clicked.
I have created a plnkr for this, please help. Ideally it should be fired only once.
$scope.treeOptions = {
checkboxes: {
checkChildren: true
},
dataBound: function(e) {
$scope.attachChangeEvent(e);
}
};
Event change code:
$scope.attachChangeEvent = function(e) {
var dataSource = e.sender.dataSource;
// issue : change event is getting called multiple times for every click on checkbox
dataSource.bind("change", function(e) {
var selectedNodes = 0;
var checkedNodes = [];
$scope.checkedNodeIds(dataSource.view(), checkedNodes);
for (var i = 0; i < checkedNodes.length; i++) {
var nd = checkedNodes[i];
if (nd.checked) {
selectedNodes++;
}
}
// check the console - this is called multiple times for one checkbox click
console.log(selectedNodes);
});
};
Is there another event to attach to to have only one event fired after all checkboxes are updated? Or maybe there is a way to group all those 'change' events and fire just one instead?
The dataBound event is triggered multiple times because you're dealing with a hierarchical data source (each child DS triggers the event, and it bubbles up). As a result, you're binding the change handler multiple times.
You should instead bind the change event from your initTree method; snippet:
var knobj = new kendo.data.HierarchicalDataSource({
data: arrayObj
});
//setting heirarchial data to scope
$scope.treeObj = knobj;
$scope.attachChangeEvent();
(updated demo)
Alternatively, you can use the dataBound event and check e.node, which is apparently undefined for the last time dataBound is triggered (demo):
dataBound: function(e) {
if (!e.node) {
$scope.attachChangeEvent();
}
}

How to update knockoutjs view model on user confirm?

I have a edit in place section to which I want to add a confirmation of changes before the knockoutjs model is updated.
Here's the jsFiddle example of what I have now.
Here's what I would like it to do.
User clicks on editable section
textbox appears with save/cancel buttons next to it.
if user makes a change and clicks save, view model is updated
if user makes a change, but decides to keep the original content, they click cancel, view model remains unchanged, texbox is hidden, and editable element remains unchanged.
The behavior of the cancel click is what I'm not sure how to implement. Can anyone suggest how this could be done?
I prefer to use custom binding handler for this.
Example http://jsfiddle.net/7v6Dx/10/
Html
<div>
<span class="editField">
<span data-bind="text: Address1">Click here to edit</span>
<input type="text" data-bind="clickEditor: Address1">
</span>
</div>​
JavaScript
ko.bindingHandlers.clickEditor = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var $element = $(element).hide();
var $text = $element.prev();
var $buttons = $("<span class='editConfirm'> \
<button class='saveEdit' type='button'>Save</button> \
<button class='cancelEdit' type='button'>Cancel</button> \
</span>").hide().insertAfter($element);
var $editElements = $buttons.add($element);
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$buttons.remove();
});
var _toggle = function(edit) {
$text[edit? 'hide' : 'show']();
$editElements[edit? 'show' : 'hide']();
}
$text.click(function(e) {
_toggle(true);
});
$editElements.find('.saveEdit').click(function() {
_toggle(false);
valueAccessor()($element.val());
});
$editElements.find('.cancelEdit').click(function() {
_toggle(false);
$(element).val(ko.utils.unwrapObservable(valueAccessor()));
});
}
, update: function (element, valueAccessor) {
$(element).val(ko.utils.unwrapObservable(valueAccessor()));
}
};
$(document).ready(function() {
var helpText = "Click here to edit";
function appViewModel() {
this.Address1 = ko.observable(helpText);
}
ko.applyBindings(appViewModel());
});​
I was thinking you could probably use a writable computed property to handle this. But it might be easier to just have to separate properties. One property is the real property and the other shadows it. When you bring up the editable section, it's actually bound to the shadow value. When the ok button is clicked, you copy the shadow value to the real value. If cancel is clicked, you do the opposite (copy the real value to the shadow value).

Categories

Resources