Remove checked property through jquery .model value not updated in knockout js - javascript

I used the jquery to remove the checked property of checkbox.The UI value is updated.However, the model value is not updated. The same old value is there in the model. If I manually check unchecked checkbox the model value is updated. I have a scenario where one checkbox is click the other checkbox should be unchecked.The required functionality is done through below code. But I need an updated value in the model.
answerClick: function (data, event) {
var element = event.target;
$(element).parents('.primaryCaseMain').find("div#" + valueToHide).find('input[type=checkbox]:checked').removeAttr('checked');
}
Here is the HTML code
<input type="checkbox" data-bind="attr:{id: $data.Id , Qid: $parent.Id , Qref: $data.QuestionRefSetStrings , Uid: $data.Uid , rel: $data.MutuallyExclusive ? 'true' : 'false'} ,checked: $data.Selected, click: $root.answerClick , if: $root.appendQrefQuestion($data.QuestionRefSetStrings, $data.NoAppendRequiredQref)">

You should use knockout to implemented this kind of functionality instead of jQuery.
In your viewmodel implement 2 properties, I call them checkbox1 and checkbox2.
var self = this; //to have access to this in anonymous functions
this.checkbox1 = ko.observable(true);
this.checkbox2 = ko.observable(false);
Then subscribe to changes of each of the observables and set the value of the other observable to false if the set value is true.
this.checkbox1.subscribe(function(newValue){
if(newValue){
self.checkbox2(false);
}
});
this.checkbox2.subscribe(function(newValue){
if(newValue){
self.checkbox1(false);
}
});
Then use the checked binding to bind the properties to the checkboxes.
<input type="checkbox" data-bind="checked: checkbox1" />
<input type="checkbox" data-bind="checked: checkbox2" />

Related

how can i listen a checked event knockout js

i have a input form with checkboxes
and i want to call a method when the checkbox is checked, and to get a value of the checkbox in the method
how can i do this by using checked binding knockout js?
i know how can i use the checked binding
<input type="checkbox" data-bind="checked : myCheckbox">
<span data-bind="text : myCheckbox"></span>
js//
var ViewModel = {
myCheckbox : ko.observable(true) ;
}
ko.applyBindings(ViewModel)
but i don't know how can i call the method when the checkbox is checked without click binding
You want to subscribe to the bound variable. In your example here, the value is just going to be true or false.
var vm = {
myCheckbox: ko.observable(true)
}
vm.myCheckbox.subscribe(function(newValue) {
console.debug(newValue);
});
ko.applyBindings(vm)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="checkbox" data-bind="checked : myCheckbox">
<span data-bind="text : myCheckbox"></span>
Maybe you could attach another binding - click? Would something like this work for you?
var ViewModel = {
myCheckbox : ko.observable(true),
handle: function(value){
console.log(value.myCheckbox());
return true;
}
}
<input type="checkbox" data-bind="checked : myCheckbox, click: handle">
<span data-bind="text : myCheckbox"></span>

Uncheck the checkbox when clicked On Button

I have checkbox list and I want to clear all checked data after Clear button.
The data is fetch from json for checkboxes.
HTML:
<div ng-repeat="data in array" >
<label class="Form-label--tick">
<input type="checkbox" id="statusid" value="{{data.id}}" class="Form-label-checkbox" ng-click="print(data.id)">
<span class="Form-label-text" id="statusname" value="{{data.name}}"> {{data.name}}</span>
</label>
</div>
JavaScript:
$scope.clearFilters = function() {
document.getElementById('statusid').value="";
document.getElementById('statusname').value="";
};
clearFilters() is called when Clear Button is clicked.But I am not able clear the checked boxes.It remains checked even after the clear button.
This code is not angular. Don't try to modify any DOM elements directly, but use the $scope variables to change their value.
In angular the checkbox return true or false so to uncheck a checkbox just change it's value to false.
so your code should look like this:
$scope.clearFilters = function() {
$scope.data.id = false;
$scope.data.name = "";
};

Radio buttons bound to knockout computed

I have some problems with knockoutjs writables computes observables I think.
I created a fiddle.
What I need is actually not so hard:
I have the nullable WeightInGramms and VolumeInMilliliters values.
These values should be bound to two input fields (only one of them should be visible).
At the top, the user can choose which of these values he want to use with the radio buttons.
At initialisation, when both of them are null, the "g" radio button should be checked, also when WeightInGramms is not null. When VolumeInMilliliters have some value, the "ml" radio button should be checked.
I used a knockoutjs writable computes observable for this, please correct me if there is a better way to do this!
So, the read function seems to work, when I change the value in the input which are bind to WeightInGramms or VolumeInMilliliters. But when I change the radio buttons nothing happens...
var ViewModel = function (data) {
var self = this;
this.VolumeInMilliliters = ko.observable(data.VolumeInMilliliters);
this.WeightInGramms = ko.observable(data.WeightInGramms);
this.GrammIsSelected = ko.computed({
read: function() {
return (!self.WeightInGramms() && !self.VolumeInMilliliters()) || !self.VolumeInMilliliters();
},
write: function (newValue) {
console.log(newValue);
return newValue;
},
owner: this
});
};
When I change the radio buttons, the corresponding input field should be visible:
<div data-bind="visible: GrammIsSelected">g is active</div>
<div data-bind="visible: !GrammIsSelected()">ml is active</div>
Edit:
When the Form is loaded for the first Time both values will be null -> the "g" button should be checked.
The observables can be initialized with:
null, null
33, null
null, 33
Both can be null, but only one of them can have a value.
If the user types in a value, and then clicks the other radio the value can be applied to the other value.
I hop it is a bit clearer
Some tips:
Make your viewModel (JS) resemble the view (HTML) as much as possible. Additionally, this avoids having to repeat too much markup. In this case, radio buttons are always lists, and so it is most convenient to store the options in an array.
Instead of testing whether GrammIsselected, you should define a selected observable that holds the selected metric. This way if you ever add more options, the code will still work without refactoring.
When to use a computed property? A computed property adds readonly value by calculating a result based on multiple observables/ variables. A writeable computed property does the same, except you can write back changes. This makes it especially useful for 'Select all' style checkboxes (see example 2 in the docs), data validation & transformations.
The absolutely clearest setup for what you want to achieve would be the following:
var ViewModel = function (data) {
this.metrics = [
{ name: 'g', value: ko.observable(data.WeightInGramms) },
{ name: 'ml', value: ko.observable(data.VolumeInMilliliters) }
];
this.selectedMetric = ko.observable(this.metrics[0]);
};
By setting an object as observable (selectedMetric), you can furthermore simplify the markup for the volume/weight input:
<div class="control-group">
<label class="control-label">choose</label>
<div class="controls" data-bind="with: selectedMetric">
<input type="text" data-bind="value: value">
<span class="help-inline" data-bind="text: '(' + name + ')'"></span>
</div>
</div>
Getting the 'final value' of your app would be as easy as retrieving selectedMetric().value().
A computed property isn't super useful here, but for example, if you wanted to provide a way for the user to both set the g/ml with radio buttons and text, you could add the following method to your viewModel:
this.selectedMetricByText = ko.computed({
read: function() {
return this.selectedMetric().name;
},
write: function(value) {
var newMetric = ko.utils.arrayFirst(this.metrics, function(metric) {
return metric.name === value;
}) || false;
this.selectedMetric(newMetric || this.metrics[0]);
}
}, this);
Fiddle
Your write function doesn't write anything, it seems?
Contrary to this other answer, based on my experience I'll give you the advice not to avoid writeable computeds: used wisely they can be very effective!
Note: in my answer I try to remain close to the original design from the question, but if you're able (have resources available) I recommend redesigning things even more based on the answer by #Tyblitz.
Here's the way you could approach this utilizing a computed:
var ViewModel = function (data) {
var self = this;
self.VolumeInMilliliters = ko.observable(data.VolumeInMilliliters);
self.WeightInGramms = ko.observable(data.WeightInGramms);
var _measurementType = ko.observable("volume");
self.MeasurementType = ko.computed({
read: function() {
return _measurementType();
},
write: function (newValue) {
_measurementType(newValue);
self.VolumeInMilliliters(newValue === "volume" ? 0 : null);
self.WeightInGramms(newValue === "mass" ? 0 : null);
}
});
};
ko.applyBindings(new ViewModel({ VolumeInMilliliters: 12 }));
label { cursor: pointer; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<label>
<input type="radio" name="measurementType" value="volume" data-bind="checked: MeasurementType">
Volume
</label>
<input data-bind="value: VolumeInMilliliters, enable: MeasurementType() === 'volume'">
<label>
<input type="radio" name="measurementType" value="mass" data-bind="checked: MeasurementType">
Weight in gramms
</label>
<input data-bind="value: WeightInGramms, enable: MeasurementType() === 'mass'">
For radio buttons, you need to use the "checked" binding.
http://knockoutjs.com/documentation/checked-binding.html
And for my personal experience (as a KO nija) I have to give you the advice: avoid writeable ko computed.
<input type="radio" name="unitSelector" value="g" data-bind="checked: unit" /> Grams</br>
<input type="radio" name="unitSelector" value="ml" data-bind="checked: unit" /> Millis</br>
Now the view model
var ViewModel = function (data) {
var self = this;
self.unit = ko.observable('g');
self.userValue = ko.observable(data.WeightInGramms);
};
Now the binding should only care about the value entered by the user, you don't need computed here and you don't need two fields...
<input type="text" data-bind="textInput: userValue ">
<span data-bind="text: unit"> </span>
It looks really too simple but that's what you need, as #Jotabe mentioned, you should take measurement and the unit as two separate things... what you do with this thing later, could be done with computed observables.
If this thing doesn't solve your problem then you should tell what you really want...

KnockoutJS "checked" binding doesn't work with observableArray and radio button lists

I have an observableArray called SelectedAttributeValueIds which I need to be bound to a radio button list using the "checked" binding. e.g.
<input type="radio" data-bind="checked: SelectedAttributeValueIds" />
However KnockoutJS is replacing the observableArray with a single value that is just observable. so instead of the SelectedAttributeValueIds having a value of [123] it will be "123"
I did this as a workaround but was wondering if there is an easier way:
<input type="radio" data-bind="event: { change: function() { $parent.SelectedAttributeValueIds([$data.ID()]); } }" />
For radio buttons, KO assumes that there will only be one "value" to write. For checkboxes, it would add/remove values from the array.
It sounds like you want to always write a single value, but have it be in an array as the only element.
One option would be to create a ko.computed to represent the item in an array. Another option would be to use a writeable ko.computed to bind against the input and have it broker the value between the formats that you want. Something like:
this.SelectedAttributeValueIds = ko.observableArray();
this.SelectedAttributeValueId = ko.computed({
read: function() {
var values = this.SelectedAttributeValueIds();
return values.length ? values[0] : [];
},
write: function(newValue) {
this.SelectedAttributeValueIds([newValue]);
},
owner: this
});

how to call a javascript function on radio button's 'checked' property?

I have N number of radio button groups in the page with auto generated names.
I want to call a javascript function as the value of the checked property. THIS LINE EXCLUDED AFTER EDIT ( Depending on the return value, the radio button needs to be checked or unchecked.)
<input type="radio" name="auto_generated_name" value="some_value" checked="test_check(args);" />
and the javascript function is
function test_check(params) {
if(conditions){
return true;
}
else
return false;
}
But that does not work. Whatever value I assign to 'checked' property, be it any javascript function or any string etc, the radio button becomes checked.
How can I achieve my goal?
EDIT:
<input type="radio" name="auto_generated_name" value="somevalue" onclick="test_check(args)"/>
4 radio buttons make a group. such N radio groups have html class names in this way : button_group_1, button_group_2, button_group_3, button_group_4 etc.
The 'args' need to be these class (i.e. radio button group) names and the corresponding values (from value="1", value="2", value="3" and value="4" ).
Cookies with the class names and values will be created inside the javascript function.
On page refresh, cookies matching with the class names will be checked and depending on the existence of the corresponding cookies, the radio button will be checked or unchecked.
How to achieve the goals/
Assuming you are using jQuery, use the change event: http://api.jquery.com/change/
The checked attribute is simply a boolean value to indicate whether the radio button should be checked, it cannot contain script, or a reference to a scripting function. Any value in the attribute will cause the radio button to be checked.
Without knowing what mechanism you are using to check each radio button - I can see an args variable but don't know what type this is - it's going to be tricky to write some code for you.
If you can make args into an array of values, then something along the lines of the following should work for you:
var args = new Array(true,false,true)
$.each(args, function(index, value) {
$("INPUT[type=radio]").eq(index).attr("checked", value)
});
Here's a fiddle to show what I mean more clearly
check this output, valid args is 'aa'.
http://jsfiddle.net/X7rcC/1
html:
<input type="radio" name="auto_generated_name" value="some_value1" checked="bb" />
js:
$(function() {
var radios = $("input[type='radio']");
$.each(radios, function(index, value){
var args = value.attributes[1].nodeValue;
test_check(args, value);
})
});
function test_check(params, value){
if(params == "aa"){
$(value).attr("checked",true);
}else
$(value).attr("checked",false);
}
try this:
Here I user a custom attribute to input named groupname. In OP's case groupname="<?php echo $radio_button_group_name; ?>". Then checking the value of this attribute OP can assign checked attribute value.
<input type="radio" name="r1" groupname="gr1"/>
<input type="radio" name="r2" groupname="gr2"/>
$('input:radio').each(function() {
if ($(this).attr('groupname') == 'gr1') {
$(this).attr('checked', true);
} else {
$(this).attr('checked', false);
}
});
Your question really boils down to:
How can I set the value of a checkbox when the page first loads? (Using a parameter stored with the checkbox)
The key insights are:
you can't store a function inside a parameter and expect it to automatically evaluate on load
you can store the data about an object inside data- properties
you can set the value of objects on page load in jQuery using the $(document).ready() event
.
<script type="text/javascript">
$(document).ready( function() { // this code runs when the page is first loaded
var radios = $("input[type='radio']"); // find all of your radio buttons
$.each(radios, function(){
var radio = $(this);
var param = radio.attr('data-param'); // retrieve the param from the object
radio.attr('checked', test_check(param) ); // set the value of the radio button
})
});
function test_check(params) {
if(conditions){
return 'checked';
}
else
return '';
}
</script>
You cannot use a checked attribute this way, because anything as the value will be the same as checked=true Even just checked checks a radio button. What you should do is use a custom attribute which will create the checked attribute:
<input type="radio" name="auto_generated_name" value="some_value" needs_check="param">
<script>
// Do test_check on param for each input
$('input:radio').each(function()
{
var radio = $(this);
var param = radio.attr('needs_check');
var condition = test_check(param);
radio.attr('checked', condition);
});
function test_check(param)
{
return true or false based on param
}
</script>
I was facing same problem and my conclusion is that don't use " " to contain a function.
Correct:
<input type="radio" name="im" id="b1" onclick=alert("hello"); />
Incorrect:
<input type="radio" name="im" id="b1" onclick="alert("hello");" />

Categories