Can't reset checked radio value to defaut value ( Vue js) - vue.js

By default, I use local pickup option, with value 1. When user changes to free delivery, there will be some condition: if zip codes are valid, then it will changed to free delivery, if not, alert message will be displayed and local pickup will be checked again. The problem is that, I can set a default delivery value to 1 if zipcode is not suitable. But radio displays checked option as 2.
<label v-for="(del, index) in delivery" :key="index">
<input type="radio" name="del" :value="del.value" v-model="defaultDelivery" #change="changeDelivery(del.value)">{{ del.label }}
</label>
export default {
data () {
return {
delivery: [
{value: 1, label: 'Local pickup'},
{value: 2, label: 'Free Delivery'}
],
accepted_zips: [
12345,
12346
],
defaultDelivery: 1,
zip_code: 78745
}
},
changeDelivery: function(val) {
if(val == 2 && !this.accepted_zips.includes(this.zip_code))
{
this.defaultDelivery = 1 //it should set 1 as checked again! But it is not aplied
alert('Sorry but currently we don't cover your area.')
}
},

Note that the apostrophe in "don't" is closing your string, and you didn't put your method in a methods section. Correcting for that, your code works fine for me.
new Vue({
el: '#app',
data() {
return {
delivery: [{
value: 1,
label: 'Local pickup'
},
{
value: 2,
label: 'Free Delivery'
}
],
accepted_zips: [
12345,
12346
],
defaultDelivery: 1,
zip_code: 78745
};
},
methods: {
changeDelivery(val) {
if (val == 2 && !this.accepted_zips.includes(+this.zip_code)) {
this.defaultDelivery = 1 //it should set 1 as checked again! But it is not aplied
alert('Sorry but currently we don\'t cover your area.')
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>ZIP code <input v-model="zip_code"></div>
<label v-for="(del, index) in delivery" :key="index">
<input type="radio" name="del" :value="del.value" v-model="defaultDelivery" #change="changeDelivery(del.value)">{{ del.label }}
</label>
</div>

Related

How to remove active classes from all buttons before making another one active?

I'm new to vue, I still don't understand everything, tell me. I have buttons that I display through v-for, I need to get the active class of only one button when pressed, all the others need to be turned off, tell me, preferably visually, how can I do it better?
I am using the method activeBtn, but this doesn't turn off the active class from the previous buttons
activeBtn(event, index) {
this.buttons[index].isActive = !this.buttons[index].isActive;
<script>
data() {
return {
buttons: [
{
label: "A",
isActive: false,
type: "border-left",
name: "BorderLeftComonent",
},
{
label: "A",
isActive: false,
type: "text-balloon",
name: "TextBalloonComponent"
},
{
label: "A",
isActive: false,
type: "dashed",
name: "DashedComponent"
},
],
};
},
methods: {
activeBtn(event, index) {
this.buttons[index].isActive = !this.buttons[index].isActive;
}
</script>
<template>
<div id="btn-box">
<button
v-for="(button, index) in buttons"
:key="index"
:class="button.isActive ? 'on' : 'off'"
#click="component = button.name, activeBtn($event, index)">
<div :class="`btn btn-${button.type}`">{{ button.label }}</div>
</button>
</div>
</template>
Since you only want to get one active button at any one point, it doesn't make sense to manage the active state inside each button.
Instead, you should manage it at group level by storing the currently selected button's id. A button would then be active when its id matches the currently selected id.
Here's an example:
new Vue({
el: '#app',
data: () => ({
buttons: [
{
id: "button-1",
label: "A",
type: "border-left",
name: "BorderLeftComonent"
},
{
id: "button-2",
label: "A",
type: "text-balloon",
name: "TextBalloonComponent"
},
{
id: "button-3",
label: "A",
type: "dashed",
name: "DashedComponent"
}
],
activeButtonId: "button-1"
}),
methods: {
activate(id) {
this.activeButtonId = id;
}
}
})
.on {
background-color: red
}
.off {
background-color: blue
}
.on, .off {
color: white
}
<script src="https://unpkg.com/vue#2/dist/vue.min.js"></script>
<div id="app">
<div>
<button
v-for="{id, type, label} in buttons"
:key="id"
:class="activeButtonId === id ? 'on' : 'off'"
#click="activate(id)"
>
<div :class="`btn btn-${type}`" v-text="label" />
</button>
</div>
</div>

How to loop a form to three time in Vuejs

I am facing an issue where I need to display one select field two times in the form and while saving the form it will save the data in an array.
What I have done is created a form and added a select form and I want it to display two times (two select form) and it will be able to select different values for two select displays
I have created a sandbox here
Any ideas are much appreciated.
You could create new variable to second value with same options as first select input and save it as array.
<template>
<div>
<b-form-select
class="mb-2 mr-sm-2 mb-sm-0"
:options="optQuality"
v-model="slcQuality"
#input="changeQuality"
>
</b-form-select>
<div>slcQuality: {{ slcQuality }}</div>
<b-form-select
class="mb-2 mr-sm-2 mb-sm-0"
:options="optQuality"
v-model="slcQuality2"
#input="changeQuality"
>
</b-form-select>
<div>slcQuality: {{ slcQuality2 }}</div>
<div>
<button #click="submit">Submit</button>
</div>
<div>submitted Data: {{ JSON.stringify(submittedData) }}</div>
</div>
</template>
<script>
export default {
data() {
return {
optQuality: [
{ value: 1, text: "Original" },
{ value: 2, text: "Kw-1" },
{ value: 3, text: "Kw-2" },
],
slcQuality: null,
slcQuality2: null, // new variable
submittedData: [],
};
},
methods: {
changeQuality() {
console.log("test");
console.log(this.slcQuality);
},
submit() {
const data = [this.slcQuality, this.slcQuality2]; //save data as array
this.submittedData = data;
console.log(data);
},
},
};
</script>
EDIT
To avoid massive code you could use an array of objects as variable or nested array like this, then loop twice in template (nested v-for).
<template>
<div>
<div v-for="(quality, i) in slcQualities" :key="i">
<div v-for="(selection, j) in quality.values" :key="j">
<div>{{ selection.name }}</div>
<b-form-select
class="mb-2 mr-sm-2 mb-sm-0"
:options="quality.options"
v-model="selection.value"
#input="changeQuality"
/>
<div>slcQuality: {{ quality.value }}</div>
</div>
</div>
<div>
<button #click="submit">Submit</button>
</div>
<div>submitted Data: {{ JSON.stringify(submittedData) }}</div>
</div>
</template>
<script>
// array of data
const qualities = [
{
options: [
{ value: 1, text: "Original" },
{ value: 2, text: "Kw-1" },
{ value: 3, text: "Kw-2" },
],
values: [
{ name: "Select 1-1", value: null },
{ name: "Select 1-2", value: null },
],
},
{
options: [
{ value: 1, text: "Original" },
{ value: 2, text: "Kw-3" },
{ value: 3, text: "Kw-4" },
],
values: [
{ name: "Select 2-1", value: null },
{ name: "Select 2-2", value: null },
],
},
];
export default {
data() {
return {
slcQualities: qualities,
submittedData: [],
};
},
methods: {
changeQuality() {
console.log("test");
console.log(this.slcQuality);
},
submit() {
const data = this.slcQualities.map((i) => i.values.map((j) => j.value)); //map the values
this.submittedData = data;
console.log(data);
},
},
};
</script>
Here's the sandbox

"prop" is undefined though it's being passed correctly

I've been following VueJS official documentation on passing data to child components with props; though I'm not working with a string template. I'm aware about what happens when your prop is camel case; you should write it as kebab case.
Nevertheless, this is not the case since it's all lowercase and won't work.
I'm using nuxt and I've separated my work into files, which are:
<template>
<div class="row">
<input type="text" name="" id="" placeholder="Write your question" v-model="text">
<select v-model="selectedField">
<option v-for="option in options" :key="option.id" :value="option.value">
{{ option.text }}
</option>
</select>
<button class="btn btn-sm btn-primary" #click="$emit('add-field')"
v-bind:class="{ disabled: ($parent.count <= 1 && $parent.count == identifier) }">
>{{identifier}}</button>
<button class="btn btn-sm btn-danger" #click="$emit('delete-field')">-</button>
</div>
Now for its JS file:
export default {
data () {
return {
options: [
{
id: 1,
value: 1,
text: "Radio"
},
{
id: 2,
value: 2,
text: "Rate"
},
{
id: 3,
value: 3,
text: "Text"
}
],
props: ['identifier'],
selectedField: 1,
text: "",
}
},
}
Now, for my parent component:
<template>
<div class="offset-md-3" id="qz">
<form-maker
v-for="item in questions" :key="item._id"
v-on:add-field="addField()"
v-on:delete-field="deleteField(item._id)"
v-bind:identifier="item._id" <<--What I want to set
ref="child"
></form-maker>
<button #click="saveForm" class="btn btn-large btn-success">SAVE</button>
</div>
</template>
Finally:
var vm = null;
export default {
layout: 'admin',
components: {
formMaker
},
data() {
return {
count: 1,
questions: [{
_id: 1//static
}]
}
},
}
What I'm trying to do is, to use the prop for some validations, nevertheless it throws the next error:
Property or method "identifier" is not defined on the instance but
referenced during render. Make sure that this property is reactive,
either in the data option, or for class-based components, by
initializing the property.
Thank you.
Here is where you go wrong. Props should not be in data(). See the code snippet below
<script>
export default {
props: ['identifier'],
data() {
return {
options: [
{
id: 1,
value: 1,
text: "Radio"
},
{
id: 2,
value: 2,
text: "Rate"
},
{
id: 3,
value: 3,
text: "Text"
}
],
selectedField: 1,
text: "",
}
}
}
</script>

Checkbox list without using v-model

Vue has a good example of using multiple checkboxes with the same name attribute bound to the same array using v-model
However, I can't use v-model for some reason so I must use #input to emit checked while keeping the value unchanged.
Its not working for me though, all the checkboxes are checked/unchecked at the same time or I have to change the value which I don't want.
Is there a workaround?
Code: https://codesandbox.io/s/71pm2wllp1?fontsize=14
Vue generates special code when compiling a template containing checkboxes bound in this way. Since you're not using v-model, you'll have to handle this functionality yourself.
Try something like this:
new Vue({
el: '#app',
data: {
checkboxes: [
{ name: 'jack', value: 'Jack' },
{ name: 'bob', value: 'Bob' },
{ name: 'alice', value: 'Alice' },
],
model: [],
},
computed: {
modelJson() {
return JSON.stringify(this.model);
},
},
methods: {
handleChange(value, checked) {
if (checked) {
this.model = this.model.concat(value);
} else {
this.model = this.model.filter(x => x !== value);
}
},
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="checkbox of checkboxes" :key="checkbox.name">
<input
type="checkbox"
:id="checkbox.name"
:name="checkbox.name"
:value="checkbox.value"
:checked="model.includes(checkbox.value)"
#change="handleChange(checkbox.value, $event.target.checked)"
/>
<label :for="checkbox.name">{{ checkbox.value }}</label>
</div>
<pre>{{ modelJson }}</pre>
</div>

How can I make a reusable "CheckAll" checkbox solution in Vue2

I am trying to create a reusable "Check All" solution for displaying a list of objects retrieved from an API.
I really like the get/set methods of computed properties that I use in this example here, https://codepen.io/anon/pen/aLeLOZ but I find that rewriting the same function over and over again and maintaining a seperate checkbox state list is tedious.
index.html
<div id="app">
<input type="checkbox" v-model="selectAll1"> Check All
<div v-for="person in list1">
<input type="checkbox" v-model="checkbox" :value="person.id">
<span>{{ person.name }}</span>
</div>
<hr/>
<input type="checkbox" v-model="selectAll2"> Check All
<div v-for="person in list2">
<input type="checkbox" v-model="checkbox2" :value="person.id">
<span>{{ person.name }}</span>
</div>
</div>
main.js
new Vue({
el: '#app',
data () {
return {
list1: [
{ id: 1, name: 'Jenna1'},
{ id: 2, name: 'Jenna2'},
{ id: 3, name: 'Jenna3'},
{ id: 4, name: 'Jenna4'}
],
list2: [
{ id: 1, name: 'Mary1'},
{ id: 2, name: 'Mary2'},
{ id: 3, name: 'Mary3'},
{ id: 4, name: 'Mary4'}
],
checkbox: [],
checkbox2: []
}
},
computed: {
selectAll1: {
get: function () {
return this.list1 ? this.checkbox.length === this.list1.length : false
},
set: function (value) {
let selected = []
if (value) {
this.list1.forEach(function (bf) {
selected.push(bf.id)
})
}
this.checkbox = selected
}
},
selectAll2: {
get: function () {
return this.list2 ? this.checkbox2.length === this.list2.length : false
},
set: function (value) {
let selected = []
if (value) {
this.list2.forEach(function (bf) {
selected.push(bf.id)
})
}
this.checkbox2 = selected
}
},
}
});
How can I make a resuable selectAll() function that will work in this example that can be included as often as needed?
Is it possible to make a class that can maintain the check box state for each list and still function as a computed property to make use of the v-model directive?
It's not the same at all, but a method based solution would be
methods: {
selectUs: function(){
if (this.checkbox.length <= this.list1.length) {
this.checkbox = Array.from(Array(this.list1.length + 1).keys())
} else {
this.checkbox = []
}
}
}
with #click="selectUs" instead of v-model="selectAll1"
(you could keep the get part of your computed properties to keep track of whether all are selected, and then use if (selectAll1) { etc } in the method)