I want to translate the title <h2>{{$t('vue.'+key.replace('contract_data.',''))}} :</h2> and messages <li>{{error}}</li>, my collegue tell me that transform all into a methods in vuejs but i don't know how to do.
this is my code:
<div v-if="getError">
<div v-for="(_errors, key) in getError">
<b-alert
v-for="error in _errors"
show
variant="danger"
>
<h2>{{ $t('vue.'+key.replace('contract_data.','')) }} :</h2>
<li>{{ error }}</li>
</b-alert>
</div>
</div>
What your colleague wants is that you extract the logic from the HTML to Javascript.
To solve this problem, your code could look like that:
template
<div v-if="getError">
<div v-for="(_errors, key) in getError">
<b-alert
v-for="error in _errors"
show
variant="danger"
>
<h2>{{ formatKey(key) }} :</h2>
<li>{{ error }}</li>
</b-alert>
</div>
</div>
script
export default {
methods: {
formatKey (key) {
return this.$t('vue.' + key.replace('contract_data.', ''))
}
}
}
Bonus: From a personal stand point I would suggest to add a key attribute to your v-for directives. (Doc: https://v2.vuejs.org/v2/guide/list.html#Maintaining-State)
I have a Vue2 project with Buefy extension. Then I have an array of objects which is rendered in the template with one select component for each item. Everything works, but if I trigger #input event on one of the select elements it triggers input event for all selects in the list. I dont understand what is wrong with that.
<div v-for="(inv, index) in pendingInvitations" :key="index" class="columns is-desktop">
<div class="column is-4">{{inv.email}}</div>
<div class="column is-4">
<b-field class="mb-5">
<b-select v-if="invitationRoles"
:input="changeInvitationRole(index)"
v-model="pendingInvitations[index].role"
:placeholder="role">
<option v-for="(value, key) in invitationRoles"
:key="key"
:value="value">
{{ value }}
</option>
</b-select>
</b-field>
</div>
</div>
...
changeInvitationRole(index){
console.log(index);
},
If I change the role and there are three items in the list the console.log() writes 0, 1, 2 as indexes for all items. Why it happens to me? I expect only current itmes index in the log.
Try replacing input with change
I have a v-for thats reading different .md files which have a image property in their front matter.
I am trying to change my div's background-image But it has to read that url taken from the files frontmatter.
this is the code:
<div v-for="item in projectsList" class="li" >
<div style="background-image: url(https://i.pinimg.com/originals/4f/c4/92/4fc49228a940e41435b3796c18fc2346.jpg)">
<a :href="item.path" class="li">
<span>{{ item.title }}</span>
</a>
</div>
</div>
Now the issue lies in changing the style:"background-image: url(<URL>) property.
I can access the image through item.frontmatter.image,
I read about this so i tried to do an example and just for testing purposes tried to feed an image through the Data function, but to vue the Url is undefined so i need a different way of feeding a URL based image to the background.
:style:"{'background-image': url( imageURL )}"
data: function () {
return {
imageURL: 'https://i.pinimg.com/originals/4f/c4/92/4fc49228a940e41435b3796c18fc2346.jpg'
}
},
You should be able to do it like this:
<div v-for="item in projectsList" class="li" >
<div :style="{ 'background-image': `url(${item.frontmatter.image})` }">
<a :href="item.path" class="li">
<span>{{ item.title }}</span>
</a>
</div>
</div>
No data function needed here I think.
I keep getting an error when I add an item to the array which has duplicate id.
i.e.
active_widgets:Array[4]
0:Object
id:1
name:"Text Blocks"
selected:false
set:false
1:Object
id:3
name:"Bibliographies/References"
selected:false
set:false
2:Object
id:1
name:"Text Blocks"
selected:false
set:false
3:Object
id:2
name:"Free Text"
selected:"Test"
set:false
In my scenario, 'id' element may be duplicate because the user can have the same widget on the page multiple times. I want to know if I can suppress or remove the warning that VueJS keeps throwing in the console.
Same key for different v-for loops causing this warning. You can avoid this using different key for different v-for loops.
<div v-for="(item, i) in items" :key="i"></div>
<div v-for="(item, i) in items2" :key="'A'+ i"></div>
<div v-for="(item, i) in items3" :key="'B' + i"></div>
Here, A and B are just sample characters. You can basically use any character instead of those (just for uniqueness).
An alternative method:
Nesting the v-for elements inside any other element also seems to work.
<div>
<div v-for="(item, index) in items" :key="index"></div>
</div>
<div>
<div v-for="(item, index) in items2" :key="index"></div>
</div>
You need to bind to the key with a unique value. Not doing so will cause problems in your application when a change in data for a component with one key updates that component and the other component with the duplicate key.
You should assign a unique key property to each of the items in the active_widgets array and then bind the key to that property.
Without seeing any of your code, I don't know what your unique use case is. But here are a couple ways you could add a unique key property to the items in your array.
Here's an example doing that in the created method.
created() {
this.active_widgets.forEach((item, index) => this.$set(item, 'key', index));
}
If you need to add a unique key when an item is added to this array, you could maintain a counter and increment it each time an addition is made:
let WidgetCount = 0;
export default {
data() {
return { active_widgets: [] }
},
methods: {
addWidget(id, name) {
this.active_widgets.push({
id,
name,
selected: false,
set: false,
key: WidgetCount++
})
}
}
}
use different key name your problem will be solved.
<div v-for="(item, i) in items" :key="i"></div>
<div v-for="(item, j) in items2" :key="j" :data-index="j"></div>
or
<div v-for="(item, i) in items2" :key="'i+item.id" :data-index="i"></div>
<template v-for="it in items">
<li :key="it.id + '-name'">{{it.name}}</li>
</template>
https://github.com/vuejs/vue/issues/7323
<div v-for="(data, index)" in active_widgets" :key="index">
{{data.id}}
{{data.name}}
{{data.selected}}
{{data.set}}
</div>
I solved this by creating a unique key function to add keys to each of my arrays. Then using it in v-for as the key...
<div
class="postBlob"
v-for="{
key,
user,
post,
dateTime
} in localPostData.slice().reverse()"
:key="key"
>
<strong class="userBlobIndy">{{ user }} </strong>
<h2 class="postBlobIndy">
{{ post }}
<p>{{ dateTime }}</p>
</h2>
</div>
you can use this example
<template>
<div >
<div v-for="categori in blogs" id="blog-body" :key="categori.title" >
<h2 >{{categori.title}}</h2>
<h3>{{categori.contact }}</h3>
</div>
</div>
</template>
<script>
export default {
data(){
return{
blogs:[
{title:'this is title 1',contact : ' this is contact for test javascript'},
{title:'this new title ',contact : ' this is contact for vue'},
{title:'this is new title 2',contact : ' this is contact for vue js'}
]
}
},
}
</script>
I'm using the following snippet to render a list:
<div #click.prevent="myhandler($event)"><!-- Delegated event handler-->
<div class="tasks" v-for="(task, subName) in step.tasks">
<button type="button">
{{ task.caption }}
</button>
<span> {{ task.callableName }} </span>
</div>
</div>
methods: {
myhandler(e){
// Event target may be a button element.
let target = e.target;
// …
// Let's assume we know 'target' is a button element instance.
// I wish I could have access to the v-for item ("task") which is associated in some ways to the button that was clicked.
// let the_task_reference = ?;
}…
Is there a clean way so that I could reach the v-for scope specific task related to that button?
Thank you.
An alternative would be to store the index of the task on the button.
<div class="tasks" v-for="(task, index) in step.tasks">
<button type="button" :data-index="index">
{{ task.caption }}
</button>
<span> {{ task.callableName }} </span>
</div>
And in your handler get the task using the index.
myhandler(evt){
const task = this.step.tasks[evt.target.dataset.index]
...
}
Example.
If you had something stronger like an id, that would be even better.
Not Recommended
There is a hidden property, __vue__ that is added to Vue and Component root elements. Were you to iterate over a component, you would be able to do something like in this example.
I wouldn't recommend that approach because it relies heavily on Vue internals that could change from version to version, but it's there today.
The most straight-forward solution would be to put the event handler on the same div as the v-for directive and just pass in the task variable:
<div
class="tasks"
v-for="(task, subName) in step.tasks"
#click.prevent="myhandler(task, $event)"
>
<button type="button">{{ task.caption }}</button>
<span>{{ task.callableName }}</span>
</div>
If you really need to use an event handler on a parent element, you could keep track of the clicked task via a component property and add an extra click handler to the div with the v-for directive:
<div #click.prevent="myhandler($event)"
<div
class="tasks"
v-for="(task, subName) in step.tasks"
#click="clickedTask = task"
>
<button type="button">{{ task.caption }}</button>
<span>{{ task.callableName }}</span>
</div>
</div>
You would need to add a clickedTask property:
data() {
return {
clickedTask: null,
}
}
And then in the handler you could refer to the task via this.clickedTask.