Working on a SPA with Mithril.js (love it!), but having a problem with input checkboxes not behaving correctly when I assign an "onchange" listener to them.
var Widget = {
view: function(vnode) {
return m("div", [
m("input[type=checkbox]", {
id: "cb" + vnode.attrs.id,
checked: Boolean(vnode.attrs.state),
onchange: function(e) {
console.log(
(e.target.checked) ? "ON" : "OFF"
);
}
}),
m("span", vnode.attrs.name)
]);
}
}
The page will initially populate properly, with checkboxes in their correct state (on or off), but when clicking the checkbox... the checkbox element does not switch.
At first, I thought the onchange event was interrupting and blocking the DOM redraw. But, then found that if I removed the "checked: (true|false)" attribute the elements works as expected.
Of course, this is not acceptable. The checkbox state needs to be presented according to it's current on/off state in the database.
I'm unsure if this is weirdness with Mithrils DOM redraw. Or some other strange behavior with HTML checkboxes and Javascript in general.
Here is a sample illustrating the broken behavior.
https://jsfiddle.net/v1aq85kj/14/
Any ideas are appreciated!
changed the "onchange" listener to an "onclick", but still the same.
tried updating checkbox states with javascript after the page load, but seemed clunky and a bad way to address the issue
You are missing out changing the value the checkbox binds to so checked/unchecked will never change.
something like this might help on the way
onchange: function(e) {
vnode.attrs.state = e.target.checked
}
Related
This is a dumb question but I've been all over the Semantic UI site, along with searching here and I haven't found a solution.
The gist is: I have been using the code below with a Semantic dropdown list. It works fine – except that I have a table component through which the user can also make a selection (which triggers a function) – and when they do, I update the Semantic dropdown to reflect the current selection . . . and then the onChange event fires – so a function is running twice when it doesn't need to.
I tried using onSelect but that is apparently not a valid event for a dropdown. I could do some stupid hack to work around this but I'd rather just use a different event. Is there one?
$(function () {
$('#productStates').dropdown({
allowAdditions: true,
allowReselection: true,
placeholder: "Select State",
onChange: function (value, text) {
if (projectData == undefined) return;
loadStateByID(value)
}
})
});
Ok - solved this. Wish the Semantic docs were clearer on event handling.
I was trying to prevent a "loading" function from getting called twice when a user clicked on a table cell and the dropdown was updated to reflect the current selection. I update the dropdown using:
$('#productStates').dropdown('set selected', activeStateID);
The onChange event handler captured all changes and so the "load" event would fire twice. Using action, the event only fires on a user action, not on setting the dropdown state through code.
$('#productStates').dropdown({
allowAdditions: true,
allowReselection: true,
placeholder: "Select State",
action: function (value, text) {
if (projectData == undefined) return;
$(this).dropdown('set selected', value);
loadStateByID(text)
}
})
So if a user wants to check a checkbox, it will prompt a dialog if he/she have rights to tick-untick. So when he don't have rights, the state will stay the same.
I am using angularjs with kendo treeview.
$scope.options = {
checkboxes: {
checkChildren: true,
},
loadOnDemand: false,
check: onCheck,
dataSource: $scope.treeData,
template: '{{ dataItem.text}}',
schema: {
model: {
children: "List"
}
}
function onCheck(e) {
var currentItem = e.sender.dataItem(e.node);
console.log(currentItem.rights);
//if currentItem.rights= '0001'
//dataItem.checked = true else false (something like this)
}
Kendo UI's events sometime are very poorly designed. Example here: The check event is prevented but it still perform the change, what doesn't happens in the default JS behaviour. What you can do is a rollback on changes:
if (!window.confirm("Do you have the rights to change this?")) {
window.setTimeout(function (node) {
this.expand(node); // expand() creates the child list if not created yet
$(node).find('input[type="checkbox"]').prop("checked", null);
}.bind(this, e.node));
}
Demo
IKR it is ugly, but I can't figure a better way for doing that. The nice thing is that the checkbox user's clicks, is not a real checkbox, it is a span that somehow internally changes the state of a real hidden checkbox and you can't prevent it's default click behaviour! Maybe somebody in their forums could help with a better solution but I'm not sure about that.
UPDATE
In fact there was a logic error in the snippet. The check event should be:
check: function(e) {
let dataItem = this.dataItem(e.node);
if (!window.confirm("Do you have the rights to change this?")) {
window.setTimeout(function (node, currentState) {
this.expand(node); // Expand created the child list if not created yet
$(node).find('input[type="checkbox"]').prop("checked", (currentState ? "checked" : null));
this.dataItem(node).set("checked", currentState);
}.bind(this, e.node, !dataItem.checked));
}
}
Updated demo.
The bug you've reported was happening because it was changing only the element state and not the DataItem's checked property, so internally the widget was acting wierd. Also, there was another bug that, the cancel action was only changing the checkbox to unchecked state and that was wrong, since the user could be cenceling a checked checkbox, so it state has to be kept checked.
So, I have this weird IE10-Bug (IE11 works correctly):
I've got a checkbox like this:
<div class="select-row row-b">
<p>some text</p>
<label><input type="checkbox" name="checkboxGroupA" data-index="1" value="A1"/>A1</label>
</div>
Using Fancyform-jQuery-Plugin v 1.4.2, it seems there's a bug in Fancyform for IE10:
so pretend this is my checkbox (somewhat styled): [ A1 ]
Clicking somewhere inside the borders ( inside [ ] ) works. Checkbox is checked. But clicking directly on the Text (the Label, "A1") does not work, checkbox state does not change from unchecked to checked.
I added a console.log("..."); to fancyforms transformCheckbox-method right here:
check: function () {
console.log("setting check");
method.setProp(this, "checked", 1);
},
just showing me the same. "check" is not triggered, when I click at the label.
It would be great to get some hints here, for I am out of Ideas now.
Best Regards,
Dom
I had the same problem, in this case you need to bind the event because the IE version.
$(".select-row row-b label").bind('click',function(){
$('input',this).attr("checked",true);
})
Edit: Here's my working code, based on this answer. I edit this code inside here because there are several side effects you have to take care of:
this.$rowLbls = $(this.$el.find('.row-alter label')); //might be $('yourdomelement', 'yoursecond...'')
this.$rowLbls.click(function(event) {
var ele = $(this).find('input');
if( $(event.target).is("label") ) { //check exactly for label, because fired twice if not => would work just once
if(ele.is(':checked')){
ele.prop('checked', false); //prop instead of attr for true/false
} else{
ele.prop('checked', true);
}
}
});
I've got a base background image and two checkboxes. I need replace the background image (via toggle class) with the correct class depending on which checkbox is selected. If both checkboxes are selected I need it to show the black background.
http://jsfiddle.net/2k96D/6/
$('#ax_lab').change(function () {
if ($('#ax_ov').is(':checked')) {
$('.axial').toggleClass('axial_all');
} else{
$('.axial').toggleClass('axial_lab');
}
});
$('#ax_ov').change(function () {
if ($('#ax_lab').is(':checked')) {
$('.axial').toggleClass('axial_all');
} else{
$('.axial').toggleClass('axial_over');
}
});
My fiddle works perfectly when I select and deselect in the same order, however, if I de-select the checkboxes in a different order than the order I selected them in, it doesn't default back to the original class. I know there must be a flaw in my logic, I'm just having trouble finding it. Any thoughts?
You need to be more explicit with the logic. Here's what I did:
$(document).ready(function () {
function updateAxialStatus() {
var axOv = $('#ax_ov').prop('checked'),
axLab = $('#ax_lab').prop('checked');
$('.axial').removeClass('axial_all axial_lab axial_over');
if (axOv && axLab)
$('.axial').addClass('axial_all');
else if (axOv)
$('.axial').addClass('axial_over');
else if (axLab)
$('.axial').addClass('axial_lab');
}
$('#ax_lab, #ax_ov').change(updateAxialStatus);
});
That version just explicitly checks the status of the two checkboxes and updates the class to reflect the status. The same handler can be used for both checkboxes.
Note that old versions of IE may not fire the "change" event for checkboxes until the checkbox loses focus, but you can safely use "click" instead.
I limit the number of checked checkboxes but style was not correct on firefox.
Actually theres a bug on firefox with state button, see this exemple on firefox,
When you doubleclick on a button, state isnot update well if lengh > 3 (in this case ) , so i try to remove class of ui state but it doesn't work , is someone got a solution ?!
http://jsfiddle.net/mbAwC/22/
$('.limit :checkbox').change(function () {
var $cs=$(this).closest('.limit').find(':checkbox:checked');
if ($cs.length > 3) {
$(this).prop('checked', false).removeClass("ui-state-active ui-state-hover ui-state-focus").button('refresh');
regards
jess
This is a weird bug, cause it happens on the double-click event. That is why your code does not work, because on the double click no "change" event occurs. So you cannot change the status and remove the classes in "onchange".
As a fix for this funny issue I tried to add sth like this:
$('.limit label').dblclick(function () {
if (!$(this).is(':checked'))
{
$(this).removeClass("ui-state-active ui-state-hover ui-state-focus ");
}
});
This handles the weird double click and removes the styles if they where applied incorrectly on a checkbox which is not checked.