I have a quiz with three different answers (2 wrong and 1 correct). I can set the radio buttons properly, and I see the three answers, but just two of the three are clickable.
Are radio buttons thought just for two clickable elements? It seems strange to me. The
<template>
<div class="quizForm" :key="componentKey">
<div class="quizQuestContainer">
<div v-for="(question, index) in quiz.questions"
:key = index
>
<!-- Hide all questions, show only the one with index === to current question index -->
<div class="quizQuestion" v-if="index === questionIndex">
<h2> Domanda {{ questionIndex+1 }}</h2>
<p class="question"> {{ question.text }} </p>
<ol>
<li v-for="(response, index) in question.responses"
:key = index
>
<label>
<input type="radio"
:value="[response.res_value === true]"
:name="response.res_number"
v-model="userResponse"
> {{response.res_text}}
</label>
</li>
</ol>
<div class="quizQuestion" v-if="questionIndex === quiz.questions.length">
</template>
<script>
import sourceData from '#/data.json'
export default {
data(){
return {
componentKey: 0,
questionIndex: 0,
userResponse: null, //this is the present radio selection
correctAnswers: [] //this is the array of selected answers
}
},
computed:{
quiz(){
return sourceData.quizzes.find(quiz =>quiz.id === parseInt(this.id))
},
}
</script>
In the data.json I have this structure:
"questions": [
{
"text": "Questoin?",
"responses": [
{"res_text": "Answer",
"res_number": 0,
"res_value": false
},
{"res_text": "Answer",
"res_number": 0,
"res_value": true
},
{"res_text": "Answer",
"res_number": 0,
"res_value": false
}
]
},
{
"text": "Question?",
"responses": [
{"res_text": "Answer",
"res_number": 1,
"res_value": true
},
{"res_text": "Answer",
"res_number": 1,
"res_value": false
},
{"res_text": "Answer",
"res_number": 1,
"res_value": false
}
]
}
etc.
I found the problem: it was here
:value="[response.res_value === true]"
I was binding everything to the true value.
Related
Not sure what I am doing wrong here, I am calling the function incorrectly or do the html tag have to specific for the disable to work? I am trying to disable the next button before any fields have been checked, I also only want one checkbox to be selected at a time. I can get the only one checkbox to be selected a time but this stop me from disabling the button cause I can't have the field be inputs.
<div>
<button #click="handleCompanySize(100)">
<CheckIcon v-show="companySize === 100"/>
</button>
<button #click="handleCompanySize(101)">
<CheckIcon v-show="companySize === 101"/>
</button>
</div>
<button :disabled="handleCompanySize" #click="next">
Next
</button>
This is a simple requirement and looks like you overthinked about it. You can use a computed property in the :disabled attribute which returns true/false based on the checkbox selection.
Live Demo :
new Vue({
el: '#app',
data: {
employees: [
{ "id": 1, "text": "0 - 1" },
{ "id": 2, "text": "2 - 10" },
{ "id": 3, "text": "11 - 50" },
{ "id": 4, "text": "50 - 100" },
{ "id": 5, "text": "> 100" }
],
selected: []
},
computed: {
disableBtn() {
return !this.selected.length ? true : false
}
},
methods: {
uniqueCheck(e) {
this.selected = [];
if (e.target.checked) {
this.selected.push(e.target.value);
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h4>Employee Selection</h4>
<table>
<tr v-for="employee in employees">
<td>
<input type="checkbox" v-model="selected" :value="employee.id" #change="uniqueCheck">
</td>
<td>{{ employee.text }}</td>
</tr>
</table>
<button :disabled="disableBtn">
Next
</button>
</div>
here's my problem :
I'm using the VueDraggable library in order to drag and drop elements between a DragBoard.vue and a DropBoard.vue, and a specific type of element should allow to be nested when it is in the DropBoard.
I'm going to take this element as an example :
"Grouped Items"
To do that I've followed this example : https://github.com/SortableJS/vue.draggable.next/blob/master/example/components/nested-example.vue
And this is what I get when I drop "Grouped Items" into the DropBoard.vue :
IMG
As you can see, the DropBoard appears a second time inside Grouped items for whatever reason. I've supposed that the nested-draggable tag also loop what is out of the draggable tag and I've no idea how to resolve that...
📄 dragItems.JSON (used in DragBoard.vue) :
1st object is a common element
2nd object is a nestable element
[
{
"type": "Simple list",
"title": "Simple list",
"id": 1,
"properties": "this is an item property"
},
...
{
"type": "Grouped items",
"title": "Grouped items",
"id": 10,
"properties": "this is an item property",
"tasks": []
},
...
]
🚩 DropBoard.vue template:
<template>
<div class="board">
<div class="head">Mock</div>
<div class="dd-container">
<draggable
:list="tasks"
v-model="dropItems"
item-key="title"
:group="{ name: 'items', put: true }"
#change="log"
>
<template #item="{ element }">
<div
class="item"
:key="element"
>
<div>
{{ element.title }}
</div>
<nested-draggable
v-if="element.tasks"
:tasks="element.tasks"
class="group-container"
/>
<div class="trashico" :key="index">
<i class="fas fa-trash" #click="deleteItem(index)"></i>
</div>
</div>
</template>
</draggable>
</div>
</div>
</template>
🚩 DropBoard.vue script
<script>
import draggable from "vuedraggable";
export default {
name: "nested-draggable",
components: {
draggable,
},
props: {
dropItems: {
type: Array,
required: true,
},
tasks: {
required: true,
type: Array,
},
},
data() {
return {
dropItems: [],
};
},
methods: {
deleteItem(id) {
this.dropItems.splice(id, 1);
},
},
};
</script>
Here is what I found while using the Vue DevTools, it's quit explicit about the problem.
See image: IMG
My first column (Test1) is active, so the background turns orange. Why does the active class not change to the second column (Test2) when I click the radio button?
I'd like it to change the active class when the radio button is clicked.
I have the following template:
<template v-if="columns" v-for="(item, index) in columns" v-bind="item">
<div class="card-container"
:style="{'height': item.height+'%'}"
:class="{ active: item.active}">
<div class="card-inner">
<input type="radio" v-if="item.selectedDefault" checked v-model="currentInput" name="cardRadioGroup"
:value="item.id" v-on:change="updateDetails(item, index)"/>
<input type="radio" v-else v-model="currentInput" name="cardRadioGroup" :value="item.id"
v-on:change="updateDetails(item, index)"/>
<template v-if="item.gbAmount === null">
Onbeperkt
</template>
<template v-else>
{{ item.gbAmount }} GB
</template>
{{ currentInput }}
</div>
</div>
</template>
With the following Vue code:
import {onMounted} from "vue";
export default {
name: 'Card',
components: {Details},
data() {
const columns =
{
"Test1": {
"id": 1,
"gbAmount": 0,
"price": 5,
"selectedDefault": false,
"informationGet": ["bla", "bla"],
"informationUsing": "Boop.",
"recommended": false,
"height": 16.66,
"active": true,
},
"Test2": {
"id": 2,
"gbAmount": 1,
"price": 10,
"selectedDefault": false,
"informationGet": ["beh", "beh"],
"informationUsing": "Beep",
"recommended": false,
"height": 33.33,
"active": false,
},
}
return {
columns,
currentColumn: {},
checkedCard: [],
currentInput: null,
};
},
methods: {
updateDetails(item, index) {
this.currentColumn = {
...item,
name: index,
active: true,
}
console.log($(this.currentColumn));
},
},
setup() {
return {};
},
};
And CSS:
.active {
background: orange;
}
You update this.currentColumn but in template use this.columns. Correct will be:
updateDetails(item, index) {
Object.keys(this.columns).forEach(key => this.columns[key].active = false);
this.columns[index].active = true;
console.log(this.columns);
}
<template>
<div v-for="column in columns" :key="column.id">
<div
class="card-container"
:style="{ height: column.height + '%' }"
:class="{ active: column.id === currentInput }"
>
<div class="card-inner">
<input
type="radio"
name="cardRadioGroup"
:value="column.id"
v-model="currentInput"
/>
<template v-if="column.gbAmount === null"> Onbeperkt </template>
<template v-else> {{ column.gbAmount }} GB </template>
{{ currentInput }}
</div>
</div>
</div>
</template>
<script lang="ts">
import { ref } from 'vue'
const columns = [
{
id: 1,
gbAmount: 0,
price: 5,
selectedDefault: false,
informationGet: ['bla', 'bla'],
informationUsing: 'Boop.',
recommended: false,
height: 16.66,
},
{
id: 2,
gbAmount: 1,
price: 10,
selectedDefault: false,
informationGet: ['beh', 'beh'],
informationUsing: 'Beep',
recommended: false,
height: 33.33,
},
]
export default {
name: 'Card',
setup() {
const currentInput = ref(columns[0].id)
return {
columns,
currentInput,
}
},
}
</script>
I've got a json API that I'm using like this:
[{
"name": "Thing",
"id": 1234,
"total": 1,
"stock": [
{
"size": "Small",
"id": 1,
"count": 10
},{
"size": "Medium",
"id": 2,
"count": 5
},{
"size": "Large",
"id": 3,
"count": 5
}
]
}]
I'm looping over these in Vue, but want to check if anything exists in the 'stock' element outside of the v-for loop.
I can use v-if to check if the overall json exists, but can't seem to narrow it down to checking if the stock element contains anything.
Any pointers?
What about a v-if & v-else condition on the length of the stocks array? If the length is greater than zero we have stocks, so display them, else, display a message. Something like this.
Vue.component('your-component', {
template:
`
<div v-for="(item, i) in items" :key="i">
<p>{{ item.name }}<p>
<p>{{ item.id }}<p>
<div v-if="item.stock && item.stock.length > 0">
<p v-for="(stock, j) in item.stock" :key="j">
There'are {{ stock.count }} of size {{ stock.size }}.
<p>
</div>
<div v-else>
Ops... stocks not available.
</div>
</div>
`,
data () {
return {
items: []
}
},
created () {
fetch('your-api')
.then((res) => res.json())
.then((res) => { this.items = res })
}
})
I try to filter an object of array in Vue.js. have products collection in this vue component. I would like to filter this collection with select buttons. These products are food products and as default I would like to show all products but if I select the lactosefree button the I would like to show only products are lactosefree. In my database these options true or false. so for example if I have a cheese that lactose free then in the database I have a field lactosefree with value true.
I have tried to filter the array with computed property but I don't really know how to do it.
<div class="col-12 justify-content-between row filterbtn">
<label class="btn btn-primary">
<input v-model="selected" value="gluteinfree" type="checkbox" class="check2">GLUTEIN FREE
</label>
<label class="btn btn-primary">
<input v-model="selected" value="lactosefree" type="checkbox" class="check2">LAKTOZ FREE
</label>
</div>
<script>
export default{
data(){
return{
products: [
{ "id": 1, "productName": "Majomkenyérfa kivonat", "gluteinfree": true, "lactosefree": false, },
{ "id": 2, "productName": "Kókuszolaj", "gluteinfree": false, "lactosefree": true,},
{ "id": 3, "productName": "C-vitamin 80mg", "gluteinfree": true, "lactosefree": true, },
],
selected: [],
}
},
computed: {
//
},
}
</script>
As default I would like to show all the products. but when i click the gluteinfree select button I would like to show only the First and the last products where the gluteinfree is true.
Here is the code you can use for your computed. This will loop over all the products and compare each against a list of selected options
return this.products.filter(product => this.selected.every(selection => product[selection] === true));
note that it's using filter and every which for old browsers may require polyfills. You can can also convert to a more verbose for loop though.
Code:
new Vue({
el: '#app',
data() {
return {
products: [{
"id": 1,
"productName": "Majomkenyérfa kivonat",
"gluteinfree": true,
"lactosefree": false,
},
{
"id": 2,
"productName": "Kókuszolaj",
"gluteinfree": false,
"lactosefree": true,
},
{
"id": 3,
"productName": "C-vitamin 80mg",
"gluteinfree": true,
"lactosefree": true,
},
],
selected: [],
}
},
computed: {
zsir() {
return this.products.filter(prod => this.selected.every(sel => prod[sel] === true));
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="col-12 justify-content-between row filterbtn">
<label class="btn btn-primary">
<input v-model="selected" value="gluteinfree" type="checkbox" class="check2">GLUTEIN FREE</label>
<label class="btn btn-primary"><input v-model="selected" value="lactosefree" type="checkbox" class="check2">LAKTOZ FREE</label>
</div>
<ul>
<li v-for="prod in zsir" :key="prod.id">{{prod.productName}}</li>
</ul>
</div>