How to properly clear another field on checkbox click in Knockout.js? - javascript

I have a list of checkboxes and one of them is "Other" and what I want is that if "Other" is selected, then a textbox is enabled. If "Other" is not checked, then the textbox must be disabled and its content must be cleared.
Now, the problem is that when I click on the "Other" checkbox, the checkmark doesn't show up or disappear UNTIL I trigger another binding event. I must have on the way of Knockout by adding the click event handler to the "Other" checkbox.
fiddle here
HTML
<input type='checkbox' value='apple' data-bind='checked: selectedFoods' />apple
<br>
<input type='checkbox' value='banana' data-bind='checked: selectedFoods' />banana
<br>
<input type='checkbox' value='other' data-bind='checked: selectedFoods, event: {click: otherClicked}' />other
<input type='text' data-bind="text: otherFoods, attr:{disabled: selectedFoods.indexOf('other') < 0}" />
JS
$(document).ready(function () {
var BaseVM = function () {
var that = {};
return that;
};
var TestVM = function () {
var that = BaseVM();
that.selectedFoods = ko.observableArray(['apple', 'banana']);
that.otherFoods = ko.observable(null);
that.otherClicked = function () {
if (that.selectedFoods.indexOf('other') < 0) {
that.otherFoods = '';
}
};
return that;
};
var vm = TestVM();
ko.applyBindings(vm);
});

This line
that.otherFoods = '';
is wrong. You need to assign the value as an observable, since that's what it is:
that.otherFoods('');
Also, you need to evaluate your array when checking the values:
that.selectedFoods.indexOf('other') < 0
should be
that.selectedFoods().indexOf('other') < 0
Edit: and your click handler was set up wrong, see this updated fiddle:
http://jsfiddle.net/2qdu9tuo/9/
You need to return true in the click handler to let the checkbox still behave like a checkbox. Also, you're using the text binding instead of the value binding on the textbox.

First, you need to return true from your click handler, otherwise the native event would not propagate and the checkbox state will not change.
Also, when resetting the otherFoods observable, you need to invoke the observable, not override it:
that.otherClicked = function () {
if (that.selectedFoods.indexOf('other') < 0)
that.otherFoods('');
return true;
};
Another problem is that you're using the text binding handler, for your otherFoods input, instead of the value handler:
<input type='text' data-bind="value: otherFoods, attr:{disabled: selectedFoods.indexOf('other') < 0}" />
See Fiddle

Related

Angularjs click clear button inside input but no effect to binded json object

As title. I have a page with several inputs with type="text", and set them with clear buttons generated by the js code:
function SetClearButtonInTextBox(Callback) {
if (!window.document.documentMode) {
$("input").each(function () {
var im = $(this);
if (!$(this).parent().hasClass("text-input-wrapper") && !$(this).hasClass("btn")) {
$(this).wrap("<div class='text-input-wrapper'></div>");
$(this).after("<button class=\"Covered\" type=\"button\">×</button>");
}
$(this).closest("div.text-input-wrapper").find("button").mousedown(function () {
im.val("");
im.change();
//return false;
});
});
}
}
And my inputs like this:
<input name="ModelA" ng-model="dl.ModelA" ng-change="ClearText(this,dl.ModelA);" value=""/>
<input name="ModelB" ng-model="dl.ModelB" ng-change="ClearText(this,dl.ModelB);" value=""/>
And I made the "ClearText" function as:
$scope.ClearText=function(target, ngModelTo){
if (target.target.value == "") {
ngModelTo = "";
}
}
I want when I click the clear button inside input, the binded value and the textbox will also be cleared, but I found that only my textbox is cleared but the binded value isn't.
Could someone guide me to make it?

Need to run a function based on conditional

I'm trying to assign a function to a couple of checkboxes, but I only want them added based on a condition, in this case the step number of the form. This is a roundabout way of making the checkboxes readOnly AFTER they have been selected (or not). So, at step 1 I want the user to choose cb1 or cb2, but at step 2 I want to assign the function that will not let the checkboxes values be changed.
What am I doing wrong?
function functionOne() {
this.checked = !this.checked
};
if (document.getElementById("stepNumber").value == 2) {
document.getElementById("cb1").setAttribute("onkeydown", "functionOne(this)");
document.getElementById("cb2").setAttribute("onkeydown", "functionOne(this)");
}
You are passing the element in an argument, so use that:
function functionOne(elem) {
elem.checked = !elem.checked
};
You could also use properties:
document.getElementById("cb1").onkeydown = functionOne;
document.getElementById("cb2").onkeydown = functionOne;
function functionOne() {
this.checked = !this.checked
};
This is a solution that requires jquery but you can use the .click function to disable checkboxes once one is clicked.
Here is a working example:
http://jsfiddle.net/uPsm7/
Why not on the selection disable the checkbox?
Function onCheck(elm)
{
document.getElementById("cbValue").value = elm.value;
elm.disabled = true;
}
<input id="cbValue" type="hidden" />
Use the hidden input field to allow form to send data back to server.

Calling Javascript function from hidden field

How can I call a Javascript function from a hidden field?
<asp:HiddenField ID="hdnfield" onChange="callJsFunction()" runat="server" />
So what can replace onChange? because hiddenfield doesn't support onTextChanged...
why can not you use
$('#<% hdnfield.Id %>').change( function() { alert("Changed"); })
It's tricky to work with hidden fields. Try this listener i wrote. It worked for me in many different cases. I'm using jquery but you don't have to. This one is listening on value change but you can listen on any attribute.
Let say you have hidden input with some initial value:
<input id="change" type="hidden" value="SomeValue" />
Script below will check that value every 2 ses and alert for changes:
// Set empty global var for input value
inputValue = '';
listenOnChange = function() {
// Check for new value if any
checkForNewInputValue = $('#change').val();
if (inputValue == checkForNewInputValue) {
// Check after 2 sec for change
setTimeout("listenOnChange()",2000);
} else {
// Replace with new value
inputValue = checkForNewInputValue;
// Check after 2 sec for change
setTimeout("listenOnChange()",2000);
alert('IT WORKS');
}
}
$(document).ready(
inputValue = $('#change').val(), // Set Initial Value
listenOnChange() // Start listener
);
Button below will change that value. Copy, Paste and see how it works.
<button onclick="$('#change').val('1234566');">CHANGE</button>

Check/Uncheck checkbox with JavaScript

How can a checkbox be checked/unchecked using JavaScript?
Javascript:
// Check
document.getElementById("checkbox").checked = true;
// Uncheck
document.getElementById("checkbox").checked = false;
jQuery (1.6+):
// Check
$("#checkbox").prop("checked", true);
// Uncheck
$("#checkbox").prop("checked", false);
jQuery (1.5-):
// Check
$("#checkbox").attr("checked", true);
// Uncheck
$("#checkbox").attr("checked", false);
Important behaviour that has not yet been mentioned:
Programmatically setting the checked attribute, does not fire the change event of the checkbox.
See for yourself in this fiddle:
http://jsfiddle.net/fjaeger/L9z9t04p/4/
(Fiddle tested in Chrome 46, Firefox 41 and IE 11)
The click() method
Some day you might find yourself writing code, which relies on the event being fired. To make sure the event fires, call the click() method of the checkbox element, like this:
document.getElementById('checkbox').click();
However, this toggles the checked status of the checkbox, instead of specifically setting it to true or false. Remember that the change event should only fire, when the checked attribute actually changes.
It also applies to the jQuery way: setting the attribute using prop or attr, does not fire the change event.
Setting checked to a specific value
You could test the checked attribute, before calling the click() method. Example:
function toggle(checked) {
var elm = document.getElementById('checkbox');
if (checked != elm.checked) {
elm.click();
}
}
Read more about the click method here:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click
to check:
document.getElementById("id-of-checkbox").checked = true;
to uncheck:
document.getElementById("id-of-checkbox").checked = false;
We can checked a particulate checkbox as,
$('id of the checkbox')[0].checked = true
and uncheck by ,
$('id of the checkbox')[0].checked = false
Try This:
//Check
document.getElementById('checkbox').setAttribute('checked', 'checked');
//UnCheck
document.getElementById('chk').removeAttribute('checked');
I would like to note, that setting the 'checked' attribute to a non-empty string leads to a checked box.
So if you set the 'checked' attribute to "false", the checkbox will be checked. I had to set the value to the empty string, null or the boolean value false in order to make sure the checkbox was not checked.
Using vanilla js:
//for one element:
document.querySelector('.myCheckBox').checked = true //will select the first matched element
document.querySelector('.myCheckBox').checked = false//will unselect the first matched element
//for multiple elements:
for (const checkbox of document.querySelectorAll('.myCheckBox')) {
//iterating over all matched elements
checkbox.checked = true //for selection
checkbox.checked = false //for unselection
}
function setCheckboxValue(checkbox,value) {
if (checkbox.checked!=value)
checkbox.click();
}
<script type="text/javascript">
$(document).ready(function () {
$('.selecctall').click(function (event) {
if (this.checked) {
$('.checkbox1').each(function () {
this.checked = true;
});
} else {
$('.checkbox1').each(function () {
this.checked = false;
});
}
});
});
</script>
For single check try
myCheckBox.checked=1
<input type="checkbox" id="myCheckBox"> Call to her
for multi try
document.querySelectorAll('.imChecked').forEach(c=> c.checked=1)
Buy wine: <input type="checkbox" class="imChecked"><br>
Play smooth-jazz music: <input type="checkbox"><br>
Shave: <input type="checkbox" class="imChecked"><br>
If, for some reason, you don't want to (or can't) run a .click() on the checkbox element, you can simply change its value directly via its .checked property (an IDL attribute of <input type="checkbox">).
Note that doing so does not fire the normally related event (change) so you'll need to manually fire it to have a complete solution that works with any related event handlers.
Here's a functional example in raw javascript (ES6):
class ButtonCheck {
constructor() {
let ourCheckBox = null;
this.ourCheckBox = document.querySelector('#checkboxID');
let checkBoxButton = null;
this.checkBoxButton = document.querySelector('#checkboxID+button[aria-label="checkboxID"]');
let checkEvent = new Event('change');
this.checkBoxButton.addEventListener('click', function() {
let checkBox = this.ourCheckBox;
//toggle the checkbox: invert its state!
checkBox.checked = !checkBox.checked;
//let other things know the checkbox changed
checkBox.dispatchEvent(checkEvent);
}.bind(this), true);
this.eventHandler = function(e) {
document.querySelector('.checkboxfeedback').insertAdjacentHTML('beforeend', '<br />Event occurred on checkbox! Type: ' + e.type + ' checkbox state now: ' + this.ourCheckBox.checked);
}
//demonstration: we will see change events regardless of whether the checkbox is clicked or the button
this.ourCheckBox.addEventListener('change', function(e) {
this.eventHandler(e);
}.bind(this), true);
//demonstration: if we bind a click handler only to the checkbox, we only see clicks from the checkbox
this.ourCheckBox.addEventListener('click', function(e) {
this.eventHandler(e);
}.bind(this), true);
}
}
var init = function() {
const checkIt = new ButtonCheck();
}
if (document.readyState != 'loading') {
init;
} else {
document.addEventListener('DOMContentLoaded', init);
}
<input type="checkbox" id="checkboxID" />
<button aria-label="checkboxID">Change the checkbox!</button>
<div class="checkboxfeedback">No changes yet!</div>
If you run this and click on both the checkbox and the button you should get a sense of how this works.
Note that I used document.querySelector for brevity/simplicity, but this could easily be built out to either have a given ID passed to the constructor, or it could apply to all buttons that act as aria-labels for a checkbox (note that I didn't bother setting an id on the button and giving the checkbox an aria-labelledby, which should be done if using this method) or any number of other ways to expand this. The last two addEventListeners are just to demo how it works.
I agree with the current answers, but in my case it does not work, I hope this code help someone in the future:
// check
$('#checkbox_id').click()

Proper handling of input change event

It may be a correct behavior of change event, but the below behavior is bit annoying. When the value is updated from the field history (see explanation below), the event is not triggered.
Please see example code below. the result input field is updated with the change in input field 'input1'. The form and submit button is not fully relevant, but needed to submit a form to make the browser keep the history of field values.
To test:
enter any input in the field (say ABC)
Submit the form
enter first character of input from 1 (A)
use the down arrow to select the previous value + Enter
or use the mouse to select the previous value from the history
No input change is detected.
Which event/ how should this code should modify so that an event is generated whenever the input value is changed.
thanks.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body>
Result:<input type="text" id="result" readonly></input>
<form method="post" action="">
<input type="text" id="input1" />
<button type=submit>Submit</button>
</form>
<script >
$(document).ready(function() {
$('#input1').change(
function(){
$('#result').val($('#input1').val());
});
});
</script>
</body>
</html>
I think this has nothing to do with jQuery.
A change event should be dispatched when the content of a control has changed and the control loses focus. In practice, the implementation of the change event is inconsistent in browsers, e.g. Firefox dispatches a change event when radio buttons are clicked on rather then when they lose focus. Also in IE, selecting a value from a list of previous values then causing a blur event doesn't fire a change event.
Note that for form controls to be successful, they must have a name attribute with a value. A simple test case is:
<form action="#">
<input type="text" name="input1" onchange="alert('changed');">
<input type="submit">
</form>
One solution is to use the blur event instead and compare the control's current value to its defaultValue - if they're different, perform whatever it is you were going to do for the change event. If the value may be changed a number of times, after the first time you need to compare with the last value onblur rather than the defaultValue.
Anyhow, here's a function that can be called onblur to see if a text input has changed. It needs a bit of work if you want to use it with other types of form control, but I don't think that's necessary.
<form action="#">
<input type="text" name="input1" onblur="
var changed = checkChanged(this);
if (changed[0]) {
alert('changed to: ' + changed[1]);
}
">
<input type="submit">
</form>
<script type="text/javascript">
// For text inputs only
var checkChanged = (function() {
var dataStore = [];
return function (el) {
var value = el.value,
oValue;
for (var i=0, iLen=dataStore.length; i<iLen; i+=2) {
// If element is in dataStore, compare current value to
// previous value
if (dataStore[i] == el) {
oValue = dataStore[++i];
// If value has changed...
if (value !== oValue) {
dataStore[i] = value;
return [true, value];
// Otherwise, return false
} else {
return [false, value];
}
}
}
// Otherwise, compare value to defaultValue and
// add it to dataStore
dataStore.push(el, value);
return [(el.defaultValue != value), value];
}
}());
</script>
Try the keyup event:
$(document).ready(function() {
$('#input1').keyup(
function(){
$('#result').val($('#input1').val());
});
});
http://jsfiddle.net/kaptZ/7/
It seems like it's definitely a browser bug. Not much you can do besides implement your own change handler with focus and blur. This example is not very reusable, but it solved the problem and can be used as inspiration for something reusable.
http://jsfiddle.net/kaptZ/9/
var startValue;
var input1 = $('#input1');
input1.focus(function(){
startValue = this.value;
});
input1.blur(function(){
if (this.value != startValue) {
$('#result').val(this.value);
}
});
A dirty alternative is to use autocomplete="off"
It looks like this bug which was supposed to be fixed in November 2009.
In modern browsers you can use the input event and update as you type. It can be bound either to the text input:
$('#input1').bind('input', function(){
$('#result').val($('#input1').val());
});
Or to the form:
$('#input1').closest('form').bind('input', function(){
$('#result').val($('#input1').val());
});

Categories

Resources