Using grouped prismic link fields in a vuetify v-btn properly? - vue.js

I have a prismic group (link_sections) containing a bunch of fields. One of the fields is a link, because the markup I am creating with these groups is supposed to contain a button that links elsewhere on the site. The problem is that I don't know how to use prismic links properly in this context because as far as I can tell it is not possible to bind the link data inside of a v-btn like so...
<v-layout v-for="(section, index) in fields.link_sections" :key="index">
<h2>{{section.header}}</h2>
<v-btn router-link :to="{{section.link}}"></v-btn>
</v-layout>
If I just render out {{section.link}} outside of the v-btn element I can render out the text value of the link successfully, but that's about as much as I can do and obviously I want to use the text as an actual link. Anyone know how I can make a link field from a prismic group work with a v-btn element?

Your syntax is wrong, try this snippet:
<v-btn :to="section.link">Link</v-btn>. Also <b-btn></v-btn> has not router-link prop. Just pass prop to. If you pass to prop, it implies that you want that button to be a <router-link>
Denotes the target route of the link.

Related

When exactly are keys useful in Vue?

I still don't quite get the use of keys even after reading through the docs but I understand that it has to do with keeping each item unique. I've been solely adding a key when using a v-for and only to the outer most parent (not the children of the v-for. Are there any other situations when keys should be used?
<div v-for="(person,index) in people" :key="index>
<div class="name-label>
<img :src="person.img/>
<div> {{ person.name }} </div>
</div>
</div>
The key directive alongside v-for, is used to uniquely identify each parent element rendered on the v-for operation.
The same happens in Reactjs:
{elements.map((value, index) => {
return <li key={index}>{value}</li>
})}
The key directive in Vuejs is also used to force Vuejs to re-render an element that contains it every time :key receives a new value.
As #firmino-changani indicated, other uses of key is if you want Vue to force a re-render or replacement of an element or component. See key special attribute documentation:
It can also be used to force replacement of an element/component
instead of reusing it. This can be useful when you want to:
Properly trigger lifecycle hooks of a component
Trigger transitions For example:
<transition>
<span :key="text">{{ text }}</span>
</transition>
When text changes, the <span> will always be replaced instead of patched, so a transition will be triggered.
Another example, lets say you have a dialog popup to add new data and another component that needs updating once the new data was entered via the popup. This second component might have logic inside lifecycle hooks like onMounted etc. Using a :key you can force re-rending this component once the dialog popup is saved e.g.
<template>
<page>
<add-data-popup #save="myKey++" />
<show-data :key"myKey" />
</page>
</template>
From the vueJs docs around Keys:
The key special attribute is primarily used as a hint for Vue’s virtual DOM algorithm to identify VNodes when diffing the new list of nodes against the old list.
To simply put it, if a div is rendered via a For-loop the div will be identical to each other div. When a user clicks on one of these Div's and you instantiate a #click function, how will vueJs know what differentiates each of these divs? How will vue know how to reorder these div's in the correct order if you remove a middle div?
VueJs uses the key to know how to reorder the DOM when an action is taken on one of these objects in your For loop.
Here is an article fully explaining about vueJs keys, and more details on the VueJS reactivity engine which is good to know about: https://www.telerik.com/blogs/in-vue-when-do-i-actually-need-the-key-attribute-and-why

strange behavior when trying to re-render data inside slot in vue

I am getting strange behaviour when trying to dynamically update the content of a slot in Vue with Vuetify. I'm sure this is just a function of misunderstanding how slots work.
I have a slot in a custom component, like so:
<template #selectButtons="slotProps">
<v-icon #click="dropToggle(slotProps.player)"
:color="dropColor(slotProps.player)"
class="mr-5"
>
fas fa-skull-crossbones
</v-icon>
</template>
When the user clicks on the icon, it is meant to toggle the icon to different colors.
I cannot seem to get dropColor to fire on each click consistently, HOWEVER, the weird part is, if I make some change inside the <v-icon> component, like say I just add {{dropColor(slotProps.player)}} inside the v-icon tags, then all of a sudden the code will work.
But then if I do a full refresh of the page, it stops working. Then I delete that code and put it back in, then it works again!
I have tried forceUpdate and keys on the v-icon tag.
Would appreciate any help
You are trying to pass function dropColor(slotProps.player) as props. The better idea is to replace function to an object or variable and change that object/variable within method dropToggle(slotProps.player) after #click event is firing .

VueJs - Deleting a File-input component from a list

I'm still pretty new to vue.js.
I recently created some vue components to tidy up my html. The components are different inputs like text and checkbox. They update the parents data using $emit('input', val). And make sure that the components are up-to-date using props and watch() on those props.
Now there is a problem with using watch() on <input type="file />, since you cannot set the input value like you can on other input types.
Using this example:
https://jsfiddle.net/minde281/nyu73dz6/25/
I have a list of, in this case, items on a shoppinglist. You can add an image for each item.
The image is loaded and added to the list. This works fine.
To get my problem:
add an image to item1
delete that item by clicking the X-button
The result is now that item2 will have that image on the <input type="file" />. The preview works as expected since this can be set through script and therefore use watch(). But somehow vue removes the wrong part of the html markup causing the last one to be removed.
Is there a different way to solve this problem? Or is there a way to tell vue to remove the correct part of the html markup?
-Minde
Vue tries to reuse the component and thats why the selected file is in the second input after deleting the component.
To prevent that you should use the key binding like this:
<li v-for="(item, index) in items" :key="item.name">
Now the hole component gets removed and everything should work as expected.

Difference between routing inside v-btn and using router-link

I am learning Vue.js, and, following a tutorial, a is used to route the page to another. He used a button wrapped by this tag, and I found that using the routing directive inside the tag.
I was wondering, what's the difference between this two ways of going from one page to another? Both of them seems to be producing the same behavior (and I am not sending or receiving any data when changing pages).
Codes for comparison:
Using v-btn
<v-btn :to="{name: 'songs-create'}"
dark medium right bottom fab absolute
class="pink" slot="action">
<v-icon>add</v-icon>
</v-btn>
Using router-link
<router-link :to="{name: 'Hello'}" tag="span" class="logo">Tab Tracker</router-link>
Thanks in advance!
v-btn is a component of vuetifyjs whereas router-link is component of vue-router.
When you use v-btn with to attribute by passing the path object, it internally uses the vue-router's router-link component's api.
So v-btn wraps the functionality of router-link when it is used with to attribute.
The reason why he could have been used the v-btn is to accomplish some other stuff like button styles and handling other events etc.

vuejs template conditional root element

I'm making a generic vue button component.
In some cases it would be a router-link while in other cases it would be a normal anchor tag.
So basically looking for something like this.
<template>
<router-link v-if="useRouter" :to="link"></router-link>
<a v-else :href="link"></a>
</template
But a vuejs component template must have exactly one root element.
Besides making two seperate vue components or wrapping my button in an element. I can't think of any other solution.
Is there a better way to solve this?