I wanna know how to v-for on a multidimensional array with selected index, because when I go with this code it does not work.
<div v-for="button in pull.button_response[key]">
<p>test</p>
</div>
Thank you
Try this:
//===== just to remove warnings
Vue.config.productionTip = false;
Vue.config.devtools = false
//==============================
new Vue({
el: "#app",
data: {
pull: {
button_response: {
a: [
1, 2, 3, 4, 5
],
b: [
6, 7, 8, 9, 10
]
}
},
key: ['a', 'b']
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<template>
<div>
<select v-model="key">
<option value="a">a</option>
<option value="b">b</option>
</select>
<br/>
<div v-for="button in pull.button_response[key]">
<p>{{button}}</p>
</div>
</div>
</template>
</div>
You can use both, index and object like an enum, so
<div v-for="(index, button) in pull" :key="index">
<p>test {{ button[index] }}</p>
</div>
Related
So let's say I have a list.
<div>
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
</ul>
</div>
I only want every item after Item1 to be visible once a user clicks a button.
I could do this easily by creating a boolean called showItem, set it to false and then create a click event that sets it to true in a method.
<div #click="showItemBtn">
<ul>
<li>Item1</li>
<li v-if="showItem">Item2</li>
<li v-if="showItem">Item3</li>
</ul>
</div>
method: {
showItemBtn() {
this.showItem = true
}
}
But is there a more clean way of doing this, so I don't have to add a v-if statement to every single item that comes after Item1?
I'd add a v-for logic to the items with a reactive bool value with adding the click logic in the template. Here You don't need to have the click methoh in the Vue logic.
new Vue({
el: "#app",
data: {
showItem: false,
// You can add your list items here
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div #click="showItem = true">
<ul>
<li>Item1</li>
<li v-for="index in 3" v-if="showItem">Item{{ index + 1 }}</li>
</ul>
</div>
</div>
You can use v-for for your items:
new Vue({
el: "#demo",
data() {
return {
items: ['Item1', 'Item2', 'Item3'],
showItem: false
}
},
methods: {
showItemBtn() {
this.showItem = true
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<div #click="showItemBtn">
<ul>
<li>Item</li>
<div v-for="item in items">
<li v-if="showItem">{{ item }}</li>
</div>
</ul>
</div>
</div>
Wrap the elements into the <template> element and use the v-if directive to the <template> only once.
new Vue({
el: "#app",
data() {
return {
showItem: false,
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div #click="showItem = !showItem">
<ul>
<li>Item1</li>
<template v-if="showItem">
<li>Item2</li>
<li>Item3</li>
</template>
</ul>
</div>
</div>
If looping is possible you can try the below way as well. I used the key as a unique id for demonstration, you can use anything which is unique.
new Vue({
el: "#demo",
data() {
return {
items: ['Item1', 'Item2', 'Item3'],
showItem: false
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<div #click="showItem = !showItem">
<ul>
<template v-for="(item,index) in items">
<!-- If first item show direct otherwise check condition -->
<li :key="index" v-if="index == 0 || showItem">
{{ item }}
</li>
</template>
</ul>
</div>
</div>
I have an array of products to fill (Product fields: {type:"",name:""}).
There is a variable that takes the number of products to enter. Then, for each product, a separate div is rendered with one select and one input text.
I need to get data from each such block and put them in an array.
<div v-for="n in parseInt(countProd)" :key="n">
<div>
<select>
<option>option1</option>
<option>option2</option>
<option>option3</option>
</select>
<input placeholder="Product name">
</div>
</div>
Let me know if this make sense.
new Vue({
el: '#app',
data() {
return {
title: "Vue 2 app",
countProd:0,
products:[]
};
},
watch:{
countProd(newVal,old){
console.log(old,newVal)
this.products=Array.from({length:newVal},(v,i)=>{
return { type:'1', name:''}
})
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
No. of Products:
<input v-model="countProd" />
<div v-for="(p,n) in products" :key="n">
<div>
<select v-model="products[n].type">
<option value="1">option1</option>
<option value="2">option2</option>
<option value="3">option3</option>
</select>
<input placeholder="Product name" v-model="products[n].name">
</div>
</div>
<p v-if="products.length>0">{{products}}</p>
</div>
Let's say I have component like this:
<template>
<div>
<div v-for="n in 2" :key="n">
<div v-for="i in 2" :key="i">
<input type="number" v-model="foo[n][i]">
</div>
</div>
<pre>{{ foo }} </pre>
</div>
</template>
This render 4 inputs. Now when I enter something into this inputs for example 1 to 4 to each I would like foo to become:
[
[1,2],
[3,4]
]
instead I have an error
TypeError: Cannot read property '1' of undefined
Your error is from the fact that the n and i indexes start at 1 in the v-for
Also for a more generic approach you could generate an array from the dimensions in your created lifecycle.
Vue.config.devtools = false;
Vue.config.productionTip = false;
var app = new Vue({
el: '#app',
data: {
x: 2,
y: 2,
array: []
},
created() {
for (let i = 0; i < this.y; i++) {
let row = [];
for (let j = 0; j < this.x; j++) {
row.push(0);
}
this.array.push(row);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="n in y" :key="n" style="display:flex">
<div v-for="i in x" :key="i">
<input type="number" v-model.number="array[n - 1][i - 1]">
</div>
</div>
{{array}}
</div>
you can try this solution: by adding a method to initial new object if it's undefined
<template>
<div>
<div v-for="n in 2" :key="n">
<div v-for="i in 2" :key="i">
<input type="number" v-model="getfoo(n)[i]">
</div>
</div>
<pre>{{ foo }} </pre>
</div>
</template>
methods: {
getfoo(n) {
if(!this.foo[n]) this.foo[n] = {}; // or = []
return this.foo[n];
},
}
I've got input fields on one side of the page which is then displayed into boxes on the other side that actively shows what a user has inputted but in an organized way. I need to actively search the input fields for a specific string, in this case 'key' and then it would instantly change to a value stored in data. I've got a searchkeyword() function that should go through the array of objects where input fields are stored but haven't made it work just yet.
For example, if user types in 'key this is david' in input1 then it would change 'key' to it's stored value which is 'hello'. The value of key is also changing if a user clicks on other options. Really don't know where to go from here so any input helps :)
var app = new Vue({
el: '#app',
data: {
activeKeyword: 'HELLO',
inputs: [
{
input1: 'oranges',
input2: 'Online',
input3: 'Free'
}
]
},
methods: {
searchKeyword() {
for(var x = 0; x < this.ads.length; x++){
for(var input in this.inputs[x]){
if(this.ads[x] !== "boolean"){
this.ads[x][input] = String(this.inputs[x][input]).replace(/_keyword_/g, this.activeKeyword)
}
}
}
}
}
})
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="box" v-for="(key, index) in inputs">
<div>
<span class="headline-ok">{{key.input1}} | </span>
<span class="headline-ok">{{key.input2}} | </span>
<span class="headline-ok">{{key.input3}}</span>
<br>
</div>
</div>
<div class="box" v-for="(key, index) in inputs">
<div class="form-inputs">
<label class="label is-capitalized">Input 1</label>
<div class="field">
<div class="control is-expanded">
<input class="input" type="text" v-model="key.input1">
</div>
</div>
</div>
<div class="form-inputs">
<label class="label is-capitalized">Headline Two </label>
<div class="field">
<div class="control is-expanded">
<input type="text" v-model="key.input2" class="input">
</div>
</div>
</div>
<div class="form-inputs">
<label class="label is-capitalized">Headline Three </label>
<div class="field">
<div class="control is-expanded">
<input type="text" v-model="key.input3" class="input">
</div>
</div>
</div>
</div>
</div>
Use a filter method to search for the matching substring of each input:
new Vue({
el: '#app',
filters: {
keyword(value, key, replacer) {
return (value && value.includes(key)) ? value.replace(key, replacer) : value
}
},
data() {
return {
replacer: 'Hello',
inputs: [{
key: 'foo',
model: null
},
{
key: 'bar',
model: null
},
{
key: 'baz',
model: null
}
],
demo: '',
demoString: 'Watch as blah is replaced with Hello'
}
},
mounted () {
let index = 0
setInterval(() => {
this.demo += this.demoString.charAt(index)
if (this.demo === this.demoString) {
this.demo = ''
index = 0
} else {
index++
}
}, 250)
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<template v-for="(i, j) in inputs">
<label>Replace {{ i.key }} with {{ replacer }}</label>
<input v-model="i.model" :key="`input-${j}`">
<p :key="`p-${j}`">{{ i.model | keyword(i.key, replacer) }}</p>
</template>
<hr/>
<label>{{ this.demoString }}</label>
<input v-model="demo">
<p>{{ demo | keyword('blah', 'Hello') }}</p>
</div>
How can I initially mark first radio-button as 'checked'?
items =
[
{txt: 'foo', val: 1},
{txt: 'bar', val: 2}
]
<div v-for="item in items">
<input name="myfield" type="radio" v-bind:value="item.val" v-bind:checked="item.val==comparisonvalue">
<label>{{ item.txt }}</label>
</div>
You probably want to use v-model to bind the input to your data, in which case set an item (e.g. myInput) in your data and then initialize it with the first value in your items array:
new Vue({
el: '#app',
data: {
myInput: 1,
items:
[
{txt: 'foo', val: 1},
{txt: 'bar', val: 2}
]
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id='app'>
<div v-for="item in items">
<input
name="myfield"
type="radio"
v-bind:value="item.val"
v-model="myInput">
<label>{{ item.txt }}</label>
</div>
</div>
Under most circumstances, you might get the items from an API call, and then you can initialize it in created:
new Vue({
el: '#app',
data: {
myInput: null,
items: null
},
created () {
this.items = [
{txt: 'foo', val: 1},
{txt: 'bar', val: 2}
] // or from an API call
this.myInput = this.items[0].val
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id='app'>
<div v-for="item in items">
<input
name="myfield"
type="radio"
v-bind:value="item.val"
v-model="myInput">
<label>{{ item.txt }}</label>
</div>
</div>
Or get the index in v-for and then check whether index === 0 at the input:
new Vue({
el: '#app',
data: {
items:
[
{txt: 'foo', val: 1},
{txt: 'bar', val: 2}
]
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id='app'>
<div v-for="(item, index) in items">
<input
name="myfield"
type="radio"
v-bind:value="item.val"
v-bind:checked="index === 0">
<label>{{ item.txt }}</label>
</div>
</div>