Buefy Vue2 select does not react on input event - vue.js

I have a code where I need to iterate over the array of objects and every one of them have a b-select inside. This select should react on input event but it deos nothing. The event is triggered on the first render but then it stops trigger event at all. Also the :v-model does not react on role change. The value is still the same.
<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)"
:model="pendingInvitations[index].role"
:placeholder="$t('company.users.invitation.roles-placeholder')">
<option v-for="(value, key) in invitationRoles"
:key="key"
:value="value">
{{ value }}
</option>
</b-select>
</b-field>
</div>
</div>
The changeInvitationRole method looks like
changeInvitationRole(index){
console.log('aaaaaaa'); // Does not trigger after the change
console.log(index);
},
InvitationRoles looks like
{
aaa:"aaa",
bbb:"bbb",
ccc:"ccc",
user:"user,
}
PendingInvitations array looks like
[
{
active:1,
deleted:0
email:"xxxxxxxx#gmail.com"
id:8
role:"user"
token:"7l1nd8j2re"
}
]
Thanks for any help.

":" is bind sign. Methods are using "#" sign. Change to #input.native

Related

How to transform this to a function in vuejs

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)

Vue2 generated select triggers event for every other selects

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

Change element background-image inside a v-for

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.

[Vue warn]: Duplicate keys detected: x. This may cause an update error

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>

Vuejs - Event delegation and v-for context reference

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.