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!
Related
I need to know if a radio button has been selected to hide / show other options.
<input #r4 type="radio" name="x">
<span>Group</span>
<div class="subOption" *ngIf="r4.checked"></div>
div.subOption must be displayed when it has been selected.
it's correct?¿
I would just create a new boolean variable in the component, that you set as true when radio button has been checked. With that boolean you then display the div. So for example:
isChecked: boolean = false; // our new variable
<input type="radio" name="x" (click)="isChecked = true">
<div *ngIf="isChecked">
<!-- Your code here -->
</div>
EDIT: As to multiple radiobuttons... as mentioned in a comment, radio buttons seems at this point be kind of buggy with Angular. I have found the easiest way to deal with radio buttons seems to be using a form. So wrap your radio buttons in a form, like so:
<form #radioForm="ngForm">
<div *ngFor="let val of values">
<input (change)="changeValue(radioForm.value)" type="radio" [value]="val.id" name="name" ngModel />{{val.name}}
</div>
</form>
whereas on radio button would look like the following in this example:
{
id: 1,
name: 'value1'
}
In the form there is a change event, from which we pick up the chosen radio button value.
(change)="changeValue(radioForm.value)"
Then I would just play with boolean and the value chosen:
changeValue(val) {
this.valueChosen = true; // shows div
this.chosenVal = val.name; // here we have the value chosen
}
A plunker to play with: here
I'm new in Vue, and I'm really in doubt about something. Well, I'm in doubt about the way we handle click event in Vue and jQuery. For me, at this moment, jQuery seems to be more simple to achieve.
in jQuery we just do that:
HTML:
<div class="jquery-radio">
Radio 1 <input type="radio" name="radio" class="choose-radio" value="Radio1" checked>
<br>
Radio 2 <input type="radio" name="radio" class="choose-radio" value="Radio2">
jQuery
$('.choose-radio').click(function() {
$('.choose-radio:checked').val() == 'Radio1' ? alert('Radio 1') :
$('.choose-radio:checked').val() == 'Radio2' && alert('Radio 2 ');
});
So, my doubt is. How to achieve this, using Vue? I tried to do this, but as I said, jQuery seems to be more simple, because instead of add #click="myMethod()" i just do what I want, selecting the element (class) $('.choose-radio);
HTML:
<div class="jquery-radio">
Radio 1 <input type="radio" name="choose-radio-vue" class="choose-radio-vue" value="Radio1" checked #click="showRadio1()">
<br>
Radio 2 <input type="radio" name="choose-radio-vue" class="choose-radio-vue" value="Radio2" #click="showRadio2()">
Vue
var app = new Vue ({
el: ".jquery-radio",
methods: {
showRadio1: function() {
alert("Show 1");
},
showRadio2: function() {
alert("Show 2");
}
}
});
Check Fiddle
These examples above, is basic. In my project, I'll show different sections based on the value previously chosen in radio. I'm realy confused in Vue.
Hope you guys can clarify this information for me!
You can add the same handler and pass in the event object, which you can later use to retrieve the current element. Here's an working example:
var app = new Vue ({
el: ".jquery-radio",
methods: {
show: function(event) {
var value = event.target.value
console.log(value)
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
<div class="jquery-radio">
Radio 1
<input type="radio" name="choose-radio-vue" class="choose-radio-vue" value="Radio1" checked #click="show($event)">
<br>
Radio 2
<input type="radio" name="choose-radio-vue" class="choose-radio-vue" value="Radio2" #click="show($event)">
</div>
PS: also, your jQuery approach is far from optimal, as it may yield errors if there are more elements that have the .choose-radio class. What you need is something like:
$('.choose-radio').click(function() {
var value = $(this).val() // value of the selected object
});
It's a pretty different way of thinking. With Vue you want to change data and let Vue handle the DOM manipulation for you. I'd use v-model and toggle the visibility of sections based on that.
new Vue({
data: {
section: 'Radio 1'
}
}).$mount('#app')
label {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
<div id="app">
<label><input name="section" type="radio" v-model="section" value="Radio 1"> One</label>
<div v-if="section === 'Radio 1'">
Radio One Is Selected!
</div>
<label><input name="section" type="radio" v-model="section" value="Radio 2"> Two</label>
<div v-if="section === 'Radio 2'">
Radio Two Is Selected!
</div>
<label><input name="section" type="radio" v-model="section" value="Radio 3"> Three</label>
<div v-if="section === 'Radio 3'">
Radio Three Is Selected!
</div>
</div>
I'm building a practice app. I've got a working filter system using checkboxes and radio buttons. I need a way to replace them with buttons that I can animate. For my plunk I'll use buttons with text, but then offline I'll replace them with images. Here's a sample of my work:
HTML
<h2>Type</h2>
<label class="btns">
<input type="radio" name="vegMeat" value="" ng-model="type.searchVeg" ng-checked="true">All
</label>
<label class="btns">
<input type="radio" name="vegMeat" value="veg" ng-model="type.searchVeg">Vegetarian
</label>
<label class="btns">
<input type="radio" name="vegMeat" value="meat" ng-model="type.searchVeg">Meat
</label>
</div>
JavaScript
.filter('searchType', function() {
return function(foods, search) {
var filtered = [];
if (!search) {
return foods;
}
angular.forEach(foods, function(food) {
if (angular.lowercase(food.type).indexOf(angular.lowercase(search)) != -1) {
filtered.push(food);
}
});
return filtered;
};
sample plunk
https://plnkr.co/edit/xk1VcCfAsVknyahux4fw?p=preview
PS I know mine is not the most efficient way of doing it, but I'm still a beginner. The buttons are my main concern but if anyone does have suggestions on how to improve the code itself, please feel free to provide an example. This is just a sample of my plunk. My full one has another 5 sets of buttons and many more recipes.
I would like to conditionally disable a button based on a radio and checkbox combination. The radio will have two options, the first is checked by default. If the user selects the second option then I would like to disable a button until at least one checkbox has been checked.
I have searched at length on CodePen and Stack Overflow but cannot find a solution that works with my conditionals. The results I did find were close but I couldn't adapt them to my needs as I am a Javascript novice.
I am using JQuery, if that helps.
If needed:
http://codepen.io/traceofwind/pen/EVNxZj
<form>
<div id="input-option1">First option: (required)
<input type="radio" name="required" id="required" value="1" checked="checked">Yes
<input type="radio" name="required" id="required" value="2">No
<div>
<div id="input-option2">Optionals:
<input type="checkbox" name="optionals" id="optionals" value="2a">Optional 1
<input type="checkbox" name="optionals" id="optionals" value="2b">Optional 2
<div>
<div id="input-option3">Extras:
<input type="checkbox" name="extra" id="extra" value="3">Extra 1
<div>
<button type="button" id="btn">Add to Cart</button>
</form>
(Please excuse the code, it is in short hand for example!)
The form element IDs are somewhat fixed. The IDs are generated by OpenCart so I believe the naming convention is set by group, rather than unique. I cannot use IDs such as radio_ID_1 and radio_ID_2, for example; this is an OpenCart framework facet and not a personal choice.
Finally, in pseudo code I am hoping someone can suggest a JQuery / javascript solution along the lines of:
if radio = '2' then
if checkboxes = unchecked then
btn = disabled
else
btn = enabled
end if
end if
Here is a quick solution and I hope that's what you were after.
$(function() {
var $form = $("#form1");
var $btn = $form.find("#btn");
var $radios = $form.find(":radio");
var $checks = $form.find(":checkbox[name='optionals']");
$radios.add($checks).on("change", function() {
var radioVal = $radios.filter(":checked").val();
$btn.prop("disabled", true);
if (radioVal == 2) {
$btn.prop("disabled", !$checks.filter(":checked").length >= 1);
} else {
$btn.prop("disabled", !radioVal);
}
});
});
Here is a demo with the above + your HTML.
Note: Remove all the IDs except the form ID, button ID (since they're used in the demo) as you can't have duplicate IDs in an HTML document. an ID is meant to identify a unique piece of content. If the idea is to style those elements, then use classes.
If you foresee a lot of JavaScript development in your future, then I would highly recommend the JavaScript courses made available by Udacity. Although the full course content is only available for a fee, the most important part of the course materials--the videos and integrated questions--are free.
However, if you don't plan to do a lot of JavaScript development in the future and just need a quick solution so you can move on, here's how to accomplish what you are trying to accomplish:
$(document).ready(function(){
$('form').on('click', 'input[type="radio"]', function(){
conditionallyToggleButton();
});
$('form').on('click', 'input[type="checkbox"]', function(){
conditionallyToggleButton();
});
});
function conditionallyToggleButton()
{
if (shouldDisableButton())
{
disableButton();
}
else
{
enableButton();
}
}
function shouldDisableButton()
{
if ($('div#input-option1 input:checked').val() == 2
&& !$('form input[type="checkbox"]:checked').length)
{
return true;
}
return false;
}
function disableButton()
{
$('button').prop('disabled', true);
}
function enableButton()
{
$('button').prop('disabled', false);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<div id="input-option1">First option: (required)
<input type="radio" name="required" id="required" value="1" checked="checked">Yes
<input type="radio" name="required" id="required" value="2">No
<div>
<div id="input-option2">Optionals:
<input type="checkbox" name="optionals" id="optionals" value="2a">Optional 1
<input type="checkbox" name="optionals" id="optionals" value="2b">Optional 2
<div>
<div id="input-option3">Extras:
<input type="checkbox" name="extra" id="extra" value="3">Extra 1
<div>
<button type="button" id="btn">Add to Cart</button>
</form>
Note that the JavaScript code above is a quick-and-dirty solution. To do it right, you would probably want to create a JavaScript class representing the add to cart form that manages the behavior of the form elements and which caches the jQuery-wrapped form elements in properties.
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).