I have some checkboxes bound to an array in my model. This works great, when you check a box the array is updated accordingly.
However when the value has changed i wish to call a method on my model to filter the results given the new values. I have tried hooking up the change event but this seems to have the values prior to the change rather than after the change.
I have illustrated my issue in a jsfiddle http://jsfiddle.net/LpKSe/ which might make this make more sense.
For completeness my code is repeated here.
JS
function SizeModel() {
var self = this;
self.sizes = ko.observableArray(["small", "medium", "large"]);
self.sizes2 = ko.observableArray(["small", "medium", "large"]);
self.getResults = function(e) {
alert(self.sizes());
};
self.getResults2 = function(e) {
alert(self.sizes2());
};
}
$(document).ready(function() {
sizeModel = new SizeModel();
ko.applyBindings(sizeModel);
});
Html
<h3>Size
<input type="checkbox" value="small" data-bind=" checked: sizes, event:{change: getResults}"/>
<span class='headertext'>Small</span>
<input type="checkbox" value="medium" data-bind=" checked: sizes, event:{change: getResults}" />
<span class='headertext'>Medium</span>
<input type="checkbox" value="large" data-bind=" checked: sizes, event:{change: getResults}" />
<span class='headertext'>Large</span>
</h3>
<h3>Size
<input type="checkbox" value="small" data-bind=" checked: sizes2, event:{click: getResults2}"/>
<span class='headertext'>Small</span>
<input type="checkbox" value="medium" data-bind=" checked: sizes2, event:{click: getResults2}" />
<span class='headertext'>Medium</span>
<input type="checkbox" value="large" data-bind=" checked: sizes2, event:{click: getResults2}" />
<span class='headertext'>Large</span>
</h3>
You don't need the change event. If you subscribe to the observableArray you will be notified when it changes, and be passed the updated array: http://jsfiddle.net/jearles/LpKSe/53/
function SizeModel() {
var self = this;
self.sizes = ko.observableArray(["3", "2", "1"]);
self.sizes.subscribe(function(updated) {
alert(updated);
});
}
In your fiddle you're missing commas in your data-bind-s, here's a fixed example: http://jsfiddle.net/4aau4/1/
Re the problem - it might be either a KnockoutJS-related problem (i.e. it updates the observableArray after the change event is fired), or something similar to what I stucked on some time ago: Checkboxes are being checked before click handler is even called
EDIT:
What a tough Sunday, I think I'm still not awake :)
Take a look at this snippet: http://jsfiddle.net/4aau4/2/ - it looks like DOM is properly updated and it's ko.observableArray that lags behind. ($('input:checked').length says how many checkboxes are actualy checked).
Related
I am trying to get an input box to be disabled when a checkbox is checked. I'm trying to use Knockoutjs to get this done, but it doesn't seem to work.
Here is my html:
<input id="input1" type="text" placeholder="Something Here"
data-bind="disable: makeInvalid"/>
<input type="checkbox" id="chk1" data-bind="checked: makeInvalid"/>
<label>Make Textarea Invalid</label>
Here is my js:
var viewModel = {
makeInvalid : ko.observable(false),
};
ko.applyBindings(viewModel, document.getElementById("chk1"));
My fiddle is here:
https://jsfiddle.net/devEngine/3ag0881z/2/
I have attempted to follow knockout's instructions on the disable binding which they say is exactly the same as the enable binding, just in reverse:
http://knockoutjs.com/documentation/enable-binding.html
Can anyone tell me what I'm doing wrong?
Any help would be much appreciated.
This one is a super easy fix. Your apply bindings is only hitting the element with id chk1. The value of the observable will only be bound in that scope. Simply remove the second argument of your ko.applyBindings and it will work just fine.
var viewModel = {
makeInvalid : ko.observable(false),
};
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input id="input1" type="text" placeholder="Something Here"
data-bind="disable: makeInvalid"/>
<input type="checkbox" id="chk1" data-bind="checked: makeInvalid"/>
<label>Make Textarea Invalid</label>
You are missing knockout from your jsFiddle.
This is incorrect
ko.applyBindings(viewModel, document.getElementById("chk1")); . You need to apply bindings to the input aswell as the checkbox. ko.applyBindings(viewModel);
See working jsFiddle:
https://jsfiddle.net/3ag0881z/4/
<input type="checkbox" data-bind="attr: { disabled: isDisabled}, checked: isActive" />
.
var viewModel = {
isDisabled: ko.observable(false),
isActive : ko.observable(false)
};
ko.applyBindings(viewModel);
this is for enable/disable checkbox and also for checked/unchecked
I'm not sure if I'm just stuck in a jQuery mindset but is there a way to update 2 model attributes with one radio button? Currently I have 2 radio buttons with one hidden. The visible one checks the second with an #click event that gets the next input and sets it to true.
var app = new Vue({
data: {
order: {
amount:
type:
}
},
methods: {
selectType: function(e) {
e.currentTarget.getElementSibling.checked = true;
}
}
});
<form>
<input type="radio" v-model="order.amount" value=15 #click="selectType">$15</input><br>
<input type="radio" v-model="order.type" value="small" style="display:none">
<input type="radio" v-model="order.amount" value=15 #click="selectType">$15</input><br>
<input type="radio" v-model="order.type" value="med" style="display:none" #click="selectType">
<input type="radio" v-model="order.amount" value=20 >$20</input><br>
<input type="radio" v-model="order.type" value="large" style="display:none">
</form>
The way I understand it, the v-model syntax is best for binding a single value. You could try to somehow make the value a JSON string and then decode it... but that sounds like a bad idea. Here are three ideas:
Using JQuery and Vue
Instead, you could give the radio buttons attributes for each value you want, and then parse out those attributes on the click callback. For example:
<input type="radio" name="rad" btn-amount="10" btn-type="small" #click="selectType($event)">$15 <br>
<input type="radio" name="rad" btn-amount="15" btn-type="med" #click="selectType">$15<br>
<input type="radio" name="rad" btn-amount="20" btn-type="large" #click="selectType">$20<br>
and then a method:
selectType: function(e) {
this.order.amount = $(e.currentTarget).attr('btn-amount');
this.order.type = $(e.currentTarget).attr('btn-type');
}
Here's a JSFiddle showing it in action.
Using Vue only
Alternatively, you could move the data for the options into the vue instance, rather than placing them on on the radio buttons. For example, add an options array to the data, and iterate over it in the HTML to create the buttons
<div v-for="option in options">
<input type="radio" name="rad" #click="selectType(option)">${{ option.amount }}
</div>
Notice that you can pass the current option in the for loop to the click handler! That means you can write selectType as:
selectType: function(option) {
this.order = option;
}
This is very clean, and what I recommend if you plan on keeping the radio-button functionality simple.
Here is a JSFiddle showing it in action.
Using Vue Components
But, if you plan on making things more complex you may want to encapsulate the radio button functionality into a component.
Consider the template:
<template id="radio-order">
<div>
<input type="radio" :name="group" #click="setOrder">${{ amount }}
</div>
</template>
and its associated component:
Vue.component('radio-order', {
template: '#radio-order',
props: ['group', 'amount', 'type'],
methods: {
'setOrder': function() {
this.$dispatch('set-order', {
amount: this.amount,
type: this.type
})
}
}
});
Now you can make <radio-order> components that dispatch a set-order event when clicked. The parent instance can listen for these events and act appropriately.
Admittedly, this method is more verbose. But, if you're thinking of implementing more complex functionality, it's probably the way to go.
Here's a JSFiddle of it in action.
Of course, there are many more ways to solve the problem, but I hope these ideas help!
I am quite new to KnockoutJS and have noticed there is quite a lot out there about radio buttons and Knockout, but unfortunately none of these could help me.
I have two radio buttons in two separate containers and can select one of them, but when selecting the other one it unfortunately doesn't change the selection even though value equals the value passed to the checked binding. Here is the simplified html:
<div>
<label>
<input
type="radio"
name="type-1"
data-bind="click: function(data, event) { setUserClass('User_Classification_1', data, event); }, checked: userClass"
value="User_Classification_1"/>
Some Text
</label>
</div>
<div>
<label>
<input
type="radio"
name="type-1"
data-bind="click: function(data, event) { setUserClass('User_Classification_2', data, event);}, checked: userClass"
value="User_Classification_2"/>
Some Text.
</label>
</div>
And here the JS :
var certViewModel = function() {
var self = this;
self.userClass = ko.observable(undefined);
self.setUserClass = function(uClass, data, event) {
self.userClass(uClass);
console.log(self.userClass());
};
};
var viewModel = new certViewModel();
ko.applyBindings(viewModel);
Here is an example in a fiddle that shows the problem:
https://jsfiddle.net/1vu0skpg/
EDIT: Fixed it myself. Returning true from the click handlers fixed the issue.
Just throwing in my two cents...
HTML
<div>
<label>
<input
type="radio"
name="type-1"
data-bind="checked: userClass"
value="User_Classification_1"/>
Some Text
</label>
</div>
<div>
<label>
<input
type="radio"
name="type-1"
data-bind="checked: userClass"
value="User_Classification_3"/>
Some Text.
</label>
</div>
This is the selected radio: <strong><span data-bind="text: userClass"></strong>
Script
var certViewModel = function() {
var self = this;
self.userClass = ko.observable();
};
var viewModel = new certViewModel();
ko.applyBindings(viewModel);
I think you were way overthinking this, unless you were triyng to do something really specific?
https://jsfiddle.net/1vu0skpg/5/
I have tried several ways to achieve this, but somehow nothing works for this.
How can I copy the "label text" of respective Radio Button, which is selected by user into the input field (Result Box) in real time?
HTML -
<ul class="gfield_radio" id="input_4_4">
Radio Buttons:
<br />
<li class="gchoice_4_0">
<input name="input_4" type="radio" value="2" id="choice_4_0" class="radio_s" tabindex="4">
<label for="choice_4_0">Hi</label>
</li>
<li class="gchoice_4_1">
<input name="input_4" type="radio" value="4" id="choice_4_1" class="radio_s" tabindex="5">
<label for="choice_4_1">Hello</label>
</li>
<li class="gchoice_4_2">
<input name="input_4" type="radio" value="3" id="choice_4_2" class="radio_s" tabindex="6">
<label for="choice_4_2">Aloha</label>
</li>
</ul>
<br />
<div class="ginput_container">
Result Box:
<br />
<input name="input_3" id="input_4_3" type="text" value="" class="medium" tabindex="3">
</div>
My attempts:
$('input').change(function() {
if (this.checked) {
var response = $('label[for="' + this.id + '"]').html();
alert(response);
}
// also this:
// if ($("input[type='radio'].radio_s").is(':checked')) {
// var card_type = $("input[type='radio'].radio_s:checked").val();
// alert('card_type');
// }
});
You need to traverse the DOM from the radio which was clicked to find the nearest label element.
$('.radio_s').change(function() {
$('#input_4_3').val($(this).closest('li').find('label').text());
});
Example fiddle
You could also use $(this).next('label') however, that relies on the position of the label element not changing. My first example means the label can be anywhere within the same li as the radio button and it will work.
Try this:
$('.radio_s').click(function() {
$("#input_4_3").val($("input:checked" ).next().text());
});
Demo: http://jsfiddle.net/WQyEw/3/
This is a slightly tricky question to answer well. The structure of your HTML implies that there may be more than one of these structures on the page. So you may have more than one set of radio buttons with a corresponding checkbox.
I have put some working code into a jsFiddle.
I made one change: all the code you had in your question is now in <div class="container">. You would need as many of these as you had groups of radio buttons and checkboxes.
You can then have jQuery code like this:
$('ul.gfield_radio').on('change', 'input[type="radio"]', function () {
var label = $('label[for="' + this.id + '"]');
$(this).closest('.container').find('input.medium').val(label.text());
});
This code is not tied to the id values in this particular bit of HTML, but would work as many times as necessary throughout the page.
Why to depend on third party library when you can achieve it with plain javascript:
<script>
document.addEventListener('DOMContentLoaded', function () {
var a = document.getElementsByName('input_4');
for (var i = 0; i < a.length; i++) {
document.getElementsByName('input_4')[i].addEventListener('change', function () {
showValue(this);
}, false);
}
}, false);
function showValue(element) {
alert(element.parentNode.getElementsByTagName('label')[0].innerHTML)
}
</script>
How can I get this list of checkboxes to be added to a div prior to their selected state, so if they are selected, they should be added to the div, if not they are removed from the list if not selected.
<div id="selected-people"></div>
<input type="checkbox" value="45" id="Jamie" />
<input type="checkbox" value="46" id="Ethan" />
<input type="checkbox" value="47" id="James" />
<input type="checkbox" value="48" id="Jamie" />
<input type="checkbox" value="49" id="Darren" />
<input type="checkbox" value="50" id="Danny" />
<input type="checkbox" value="51" id="Charles" />
<input type="checkbox" value="52" id="Charlotte" />
<input type="checkbox" value="53" id="Natasha" />
Is it possible to extract the id name as the stored value, so the id value will be added to the div instead of the value - the value needs to have the number so that it gets added to a database for later use.
I looked on here, there is one with checkboxes and a textarea, I changed some parts around, doesn't even work.
function storeuser()
{
var users = [];
$('input[type=checkbox]:checked').each(function()
{
users.push($(this).val());
});
$('#selected-people').html(users)
}
$(function()
{
$('input[type=checkbox]').click(storeuser);
storeuser();
});
So you want to keep the DIV updated whenever a checkbox is clicked? That sound right?
http://jsfiddle.net/HBXvy/
var $checkboxes;
function storeuser() {
var users = $checkboxes.map(function() {
if(this.checked) return this.id;
}).get().join(',');
$('#selected-people').html(users);
}
$(function() {
$checkboxes = $('input:checkbox').change(storeuser);
});
Supposing you only have these input controls on page I can write following code.
$.each($('input'), function(index, value) {
$('selected-people').append($(value).attr('id'));
});
Edited Due to More Description
$(document).ready(function() {
$.each($('input'), function(index, value) {
$(value).bind('click', function() {
$('selected-people').append($(value).attr('id'));
});
});
});
Note: I am binding each element's click event to a function. If that doesn't work or it isn't a good for what you are supposed to do then change it to on "change" event.
Change:
users.push($(this).val());
to:
users.push($(this).attr('id'));
This is for to bind the comma seperated values to input checkbox list
$(".chkboxes").val("1,2,3,4,5,6".split(','));
it will bind checkboxes according to given string value in comma seperated.