vuetify tabs component doesnt work correctly with flex animation - vue.js

I'm trying to get the v-tabs to work with my expand menu.
Basically when I click the toggle open, the right side menu will slide out, and inside this menu I want to use the tabs component from vuetify.
It doesn't seem to work, when clicking on the tabs, it's jumping all over the places.
It starts to work correctly when I resize the window manually. Any help please?
Here's the codepen
codepen.io/anon/pen/WmKQLp

You should be able to use a Navigation Drawer without any custom styling needed... (Vuetify has built in components for what you're trying to accomplish)..
Here is a 'quick and dirty' pseudo example showing how you can accomplish this:
Codepen Example can be found here. updated with resizing ability
EDIT:
If you did want to use your custom CSS, you will need to add an additional custom CSS class - this is happening because of the translate, among other Vuetify styles conflicting with your custom CSS...
As outlined here, add this class: (I highly advise against doing this)
.v-tabs__container {
transform: translateX(0px)!important;
}
HTML
<div id="app">
<v-app>
<v-navigation-drawer app right width="550" v-model="navigation.shown">
<v-toolbar color="primary">
<v-toolbar-title class="headline text-uppercase">
<span>t a</span><span class="font-weight-light"> B S </span>
</v-toolbar-title>
</v-toolbar>
<v-tabs>
<v-tab v-for="n in 3" :key="n">
Item {{ n }}
</v-tab>
<v-tab-item v-for="n in 3" :key="n">
<v-card flat>
<v-card-text>Content for tab {{ n }} would go here</v-card-text>
</v-card>
</v-tab-item>
</v-tabs>
</v-navigation-drawer>
<v-layout justify-center>
<v-btn #click="navigation.shown = !navigation.shown">Toggle {{ direction }}</v-btn>
</v-layout>
</v-app>
</div>
JS/Vue
new Vue({
el: "#app",
data: () => {
return {
navigation: {
shown: false,
}
};
},
computed: {
direction() {
return this.navigation.shown === false ? "Open" : "Closed"
}
},
});
EDIT: (with resizing ability)
HTML:
<div id="app">
<v-app>
<v-navigation-drawer
ref="drawer"
app
right
:width="navigation.width"
v-model="navigation.shown"
>
<v-toolbar color="primary">
<v-toolbar-title class="headline text-uppercase">
<span>t a</span><span class="font-weight-light"> b s </span>
</v-toolbar-title>
</v-toolbar>
<v-tabs>
<v-tab v-for="n in 3" :key="n">
Item {{ n }}
</v-tab>
<v-tab-item v-for="n in 3" :key="n">
<v-card flat>
<v-card-text>Content for tab {{ n }} would go here</v-card-text>
</v-card>
</v-tab-item>
</v-tabs>
</v-navigation-drawer>
<v-layout justify-center>
<v-btn #click="navigation.shown = !navigation.shown">Toggle {{ direction }}</v-btn>
</v-layout>
</v-app>
</div>
JS/Vue:
new Vue({
el: "#app",
data: () => {
return {
navigation: {
shown: false,
width: 550,
borderSize: 3
}
};
},
computed: {
direction() {
return this.navigation.shown === false ? "Open" : "Closed";
}
},
methods: {
setBorderWidth() {
let i = this.$refs.drawer.$el.querySelector(
".v-navigation-drawer__border"
);
i.style.width = this.navigation.borderSize + "px";
i.style.cursor = "ew-resize";
},
setEvents() {
const minSize = this.navigation.borderSize;
const el = this.$refs.drawer.$el;
const drawerBorder = el.querySelector(".v-navigation-drawer__border");
const vm = this;
const direction = el.classList.contains("v-navigation-drawer--right")
? "right"
: "left";
function resize(e) {
document.body.style.cursor = "ew-resize";
let f = direction === "right"
? document.body.scrollWidth - e.clientX
: e.clientX;
el.style.width = parseInt(f) + "px";
}
drawerBorder.addEventListener(
"mousedown",
function(e) {
if (e.offsetX < minSize) {
el.style.transition = "initial";
document.addEventListener("mousemove", resize, false);
}
},
false
);
document.addEventListener(
"mouseup",
function() {
el.style.transition = "";
vm.navigation.width = el.style.width;
document.body.style.cursor = "";
document.removeEventListener("mousemove", resize, false);
},
false
);
}
},
mounted() {
this.setBorderWidth();
this.setEvents();
}
});

Related

How do I capture the value of the prop in the text field?

I have a prop and currently am able to get the data of the prop, Am trying a way to capture the item of the prop when saving the form.
Is there a way where i can take the value and pass if in a hidden text-area and bind the data to the vmodel?
Any help I appreciate.
<v-dialog v-model="dialog" persistent max-width="800">
<template v-slot:activator="{ on }">
<v-btn dark v-on="on" color="primary" round> Make payment </v-btn>
</template>
<v-card>
<v-card-title class="headline primary">
<span class="white--text">Add a new Doctor Payment Record {{ queueId }}</span>
<v-btn icon dark #click.native="dialog = false" absolute right>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<v-card-text>
<users-search
:leave-selected="true"
idOnly
label="Select Doctor"
#results="setDoctor"
>
</users-search>
<div class="row px-3">
<v-autocomplete
class="px-3 col-sm-8"
v-model="expense.bank"
v-if="banks.data"
:items="banks.data"
outline
chips
label="Select bank"
item-text="name"
item-value="id"
>
</v-autocomplete>
<v-text-field
class="px-3 col-sm-8"
outline
flat
v-model="expense.amount"
type="number"
#input="expense.percentage()"
required
label="Amount *"
persistent-hint
/>
</div>
<v-text-field
class="px-3"
outline
flat
v-model="expense.total_paid"
required
label="amount paid"
persistent-hint
/>
<v-text-field
class="px-3"
outline
flat
:value="setQueue"
v-model="expense.queueId"
required
:label=queueId
persistent-hint
/>
<v-alert :value="true" type="error" v-if="errors.any()">
<div v-html="errors.display()"></div>
</v-alert>
<v-layout row wrap>
<v-flex xs12>
<v-btn
color="success"
:loading="saveLoader"
#click="recordExpense()"
>save</v-btn
>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
</v-dialog>
</template>
<script>
import NewUser from "#finance/libs/users/NewUser";
import {mapActions, mapGetters} from "vuex";
export default {
props: [
'queueId'
],
data: () => ({
dialog: false,
expense: new NewUser(),
saveLoader: false,
}),
computed: {
...mapGetters({
banks: "getBanks",
}),
balance: function () {
return parseFloat(10);
},
submitted() {
return this.expense.form.submitted;
},
contaminated() {
return this.expense.form.errorDetected;
},
errors() {
return this.expense.form.errors;
},
},
watch: {
submitted(v) {
if (v) {
this.saveLoader = false;
}
},
contaminated() {
this.saveLoader = false;
},
},
methods: {
...mapActions({
fetchBanks: "setBanks",
}),
setDoctor(user) {
this.expense.doctor_id = user.id;
},
setQueue(){
console.log(this.queueId);
this.expense.queueId = this.queueId;
},
async recordExpense() {
this.saveLoader = true;
let response = await this.expense.saveExpense();
this.saveLoader = false;
if (response) {
this.dialog = false;
this.$emit("expenseCreated");
}
},
},
mounted() {
this.fetchBanks();
}
};
</script>
The prop queueId i also want to store it along with the user information from the form.
Try this one, it should work:
<template>
<textarea v-model="hiddenValue" :style="{ display: 'none' }"></textarea>
</template>
<script>
export default {
props: [ 'queueId' ],
data() {
return {
hiddenValue: this.queueId
}
}
}
</script>
In case you will no need the prop to be modified, please bind the texarea value to the prop directly:
<textarea hidden v-model="queueId" :style="{ display: 'none' }></textarea>

How to load placeholder in cropper after upload

I'm using vue-cropper 4.1 from cropperjs with Nuxt 2.13. when my cropper load it shows a placeholder, after choosing image and uploading it, the cropper still shows the chosen image, but i wanna load the placeholder again. what should i do? i tried replace() but didn't work. here is my code:
note: there are some this in my code that u may not find the reference. they are globally added to my project via mixins. and editProduct is a state in my vuex that is added globally same as it's action.
<template>
<div class="pt-6">
<v-row class="ma-0">
<v-col cols="12" sm="12" md="5" class="pa-0" >
<v-card flat class="pb-4" max-width="450px">
<client-only>
<vue-cropper
ref="cropper"
:aspect-ratio="1/1"
:src="url"
dragMode="move"
/>
</client-only>
<v-card flat class="d-flex justify-center theme__main__color my-2">
<v-btn text icon class="mx-1 text_main_color" #click.prevent="rotate(-45)">
<v-icon>mdi-rotate-left</v-icon>
</v-btn>
<v-btn text icon class="mx-1 text_main_color" ref="flipX" #click.prevent="flipX">
<v-icon>mdi-flip-horizontal</v-icon>
</v-btn>
<v-btn text icon class="mx-1 text_main_color" #click.prevent="reset">
<v-icon>mdi-border-all-variant</v-icon>
</v-btn>
<v-btn text icon class="mx-1 text_main_color" ref="flipY" #click.prevent="flipY">
<v-icon>mdi-flip-vertical</v-icon>
</v-btn>
<v-btn text icon class="mx-1 text_main_color" #click.prevent="rotate(45)">
<v-icon>mdi-rotate-right</v-icon>
</v-btn>
<a style="display:none;" ref="flipX" href="#" #click.prevent="flipX"></a>
<a style="display:none;" ref="flipY" href="#" #click.prevent="flipY"></a>
</v-card>
<v-list container inline class="transparent text-center pa-0">
<v-list-item class="px-0">
<v-list-item class="px-1">
<v-btn
width="100%"
class="theme__btn__w text_main_color"
:loading="isSelecting"
#click="onChooseClick"
>{{lang.chooseimage}}</v-btn>
</v-list-item>
<v-list-item class="px-1">
<v-btn
width="100%"
class="theme__btn__s text_main_color"
#click.prevent="uploadImage"
:disabled="isUploading || !selectedFile"
>{{lang.upload}}</v-btn>
<input
ref="uploader"
class="d-none"
type="file"
accept="image/*"
#change="onFileChanged"
>
</v-list-item>
</v-list-item>
</v-list>
</v-card>
</v-col>
<v-col cols="12" sm="12" md="7" class="pa-0" v-if="storedImg">
<v-row class="ma-0">
<!-- img 1 -->
<v-col cols="12" sm="6" md="4" class="pa-1 mb-4" v-for="(image, index) in storedImg" :key="index">
<v-card flat>
<div tile class="rounded-r felx float-right text_main_color theme__btn__p pa-1" height="100%">
<div><v-icon class="text_main_color" medium>mdi-sort-variant</v-icon></div>
<div><span class="my-1 productlist__btn__sort">Hold to order</span></div>
</div>
<v-img class="theme__main__color rounded-l" max-width="141" :src="imagePathCreator(image.url)"></v-img>
<v-btn text class="theme__cta__color text_main_color mt-2" min-width="141" #click.prevent="deleteImg(index, image.id)">{{lang.delete}}</v-btn>
</v-card>
</v-col>
</v-row>
</v-col>
<!-- btn -->
<addproductbtn :section="section" />
</v-row>
</div>
</template>
<style>
</style>
<script>
import addproductbtn from '~/components/global/cms/addproductbtn'
import {ALERT_TYPE, ALERT_METHOD} from '~/plugins/constants.js'
import VueCropper from 'vue-cropperjs';
import 'cropperjs/dist/cropper.css';
export default {
components:{
VueCropper,
'addproductbtn': addproductbtn
},
props:['err'],
data(){
return{
isSelecting: false,
selectedFile: null,
url: null,
placeholder: '/images/placeholder/place-800.png',
section: 'img',
pImages: [],
pId: null,
cropData: null,
isUploading: false
}
},
computed:{
storedImg(){
return this.editProduct.images
}
},
methods:{
// ***** Cropper Methods ***** \\
flipX() {
const dom = this.$refs.flipX;
let scale = dom.getAttribute('data-scale');
scale = scale ? -scale : -1;
this.$refs.cropper.scaleX(scale);
dom.setAttribute('data-scale', scale);
},
flipY() {
const dom = this.$refs.flipY;
let scale = dom.getAttribute('data-scale');
scale = scale ? -scale : -1;
this.$refs.cropper.scaleY(scale);
dom.setAttribute('data-scale', scale);
},
reset() {
this.$refs.cropper.reset();
},
rotate(deg) {
this.$refs.cropper.rotate(deg);
},
getData(){
this.cropData = this.$refs.cropper.getData(true);
},
// ***** Component Methods ***** \\
onChooseClick(){
this.isSelecting = true
window.addEventListener('focus', () => {
this.isSelecting = false
}, { once: true })
this.$refs.uploader.click()
},
onFileChanged(e) {
// **** CROPPER CHOOSE FILE **** //
this.selectedFile = e.target.files[0];
if (this.selectedFile.type.indexOf('image/') === -1) {
this.noty(ALERT_TYPE[0],lang.errimagefile);
return;
}
if (typeof FileReader === 'function') {
const reader = new FileReader();
reader.onload = (event) => {
this.url = event.target.result;
// rebuild cropperjs with the updated source
this.$refs.cropper.replace(event.target.result);
};
reader.readAsDataURL(this.selectedFile);
} else {
this.noty(ALERT_TYPE[0],lang.something_wrong);
}
},
async uploadImage(){
this.getData()
if(this.notEmpty(this.selectedFile) && this.notEmpty(this.pId) &&
this.notEmpty(this.cropData)){
this.isUploading = true
const data = new FormData()
data.append('image', this.selectedFile)
data.append('pId', this.pId)
data.append('w', this.cropData.width)
data.append('h', this.cropData.height)
data.append('x', this.cropData.x)
data.append('y', this.cropData.y)
data.append('r', this.cropData.rotate)
data.append('sx', this.cropData.scaleX)
data.append('sy', this.cropData.scaleY)
let response = await this.axiosPost('product/createproimg', data)
if(this.resOk(response.status)){
const newImages = {"id": response.data.id,"url": response.data.url}
this.setEditProductImg(newImages)
this.selectedFile = null
}
}
this.isUploading = false
},
},
created(){
this.url = this.placeholder
}
}
</script>
After searching and reading the document on Cropperjs i finally found the solution.
after image is uploaded i used distroy() and then replace() like this:
async uploadImage(){
this.getData()
if(this.notEmpty(this.selectedFile) && this.notEmpty(this.editProduct.pId) && this.notEmpty(this.cropData)){
// this.isUploading = true
const data = new FormData()
data.append('image', this.selectedFile)
data.append('pId', this.editProduct.pId)
data.append('w', this.cropData.width)
data.append('h', this.cropData.height)
data.append('x', this.cropData.x)
data.append('y', this.cropData.y)
data.append('r', this.cropData.rotate)
data.append('sx', this.cropData.scaleX)
data.append('sy', this.cropData.scaleY)
let response = await this.axiosPost('product/createproimg', data)
if(this.resOk(response.status)){
const newImages = {"id": response.data.id,"url": response.data.url}
this.setEditProductImg(newImages)
this.myArray.unshift(newImages)
this.originalArray.push(newImages)
this.selectedFile = null
//*********** THIS PART REPLACE CROPPER WHITH MY PLACEHOLDER IMAGE **************\\
this.$refs.cropper.destroy()
this.$refs.cropper.replace(this.placeholder)
//**** this.placeholder is the placeholder.jpg file path in my static folder ****\\
this.isUploading = false
}else{
this.isUploading = false
}
}
this.isUploading = false
},

Vue draggable to follow v-chip-group selection

I am using Vue draggable to change the position of my v-chips. When you click on a chip, the chip shows Active and is binded to selection with its index. The problem is that when you drag a chip and change its position it does not update the selection index.
How can I make sure one follows the other?
<v-chip-group
v-model="selection"
active-class="primary--text"
column
>
<draggable v-model="items" #start="drag=true" #end="drag=false">
<v-chip v-for="(item, i) in items" :key="i"
close
draggable>
{{item.name}}
</v-chip>
</draggable>
</v-chip-group>
You can able to set the selection index using #start and #end event in draggable component
Here is the working codepen: https://codepen.io/chansv/pen/zYvOYyd?editors=1010
Find the working code here:
<div id="app">
<v-app id="inspire">
<v-card
max-width="400"
class="mx-auto"
>
<v-card-text>
<v-chip-group
v-model="selection"
column
active-class="primary--text"
>
<draggable v-model="tags" #start="dragStart" #end="dragEnd">
<v-chip v-for="(tag, i) in tags" :key="i" draggable>
{{ tag.name }}
</v-chip>
</draggable>
</v-chip-group>
</v-card-text>
</v-card>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
selection: null,
currentTag: null,
tags: [{
name: 'Shoping',
},{
name: 'Art',
}, {
name: 'Tech',
}, {
name: 'Creative Writing'
}
],
}),
methods: {
dragStart() {
if (this.tags[this.selection]) this.currentTag = this.tags[this.selection].name;
else this.currentTag = null;
},
dragEnd() {
var self = this;
if (this.currentTag) {
this.tags.forEach((x, i) => {
if (x.name === self.currentTag) self.selection = i;
});
}
}
}
})

Vuetify Navigation Drawer Drag To Resize

So I have gotten it to where the the 'drag to resize' works - it just feels a little laggy... does anyone know why this may be, and how to fix it?
I have tried forcing a refresh using vm.$forceUpdate() but that did not seem to do anything..
The CodePen can be found here.
EDIT: Added demo code working solution to this question/post. This way if something happens to the CodePen, we still have working demo code.
new Vue({
el: "#app",
data: () => {
return {
navigation: {
shown: false,
width: 200,
borderSize: 3
}
};
},
computed: {
direction() {
return this.navigation.shown === false ? "Open" : "Closed";
}
},
methods: {
setBorderWidth() {
let i = this.$refs.drawer.$el.querySelector(
".v-navigation-drawer__border"
);
i.style.width = this.navigation.borderSize + "px";
i.style.cursor = "ew-resize";
i.style.backgroundColor = "red";
},
setEvents() {
const minSize = this.navigation.borderSize;
const el = this.$refs.drawer.$el;
const drawerBorder = el.querySelector(".v-navigation-drawer__border");
const vm = this;
const direction = el.classList.contains("v-navigation-drawer--right") ?
"right" :
"left";
function resize(e) {
document.body.style.cursor = "ew-resize";
let f =
direction === "right" ?
document.body.scrollWidth - e.clientX :
e.clientX;
el.style.width = f + "px";
}
drawerBorder.addEventListener(
"mousedown",
(e) => {
if (e.offsetX < minSize) {
el.style.transition = "initial";
document.addEventListener("mousemove", resize, false);
}
},
false
);
document.addEventListener(
"mouseup",
() => {
el.style.transition = "";
this.navigation.width = el.style.width;
document.body.style.cursor = "";
document.removeEventListener("mousemove", resize, false);
},
false
);
}
},
mounted() {
this.setBorderWidth();
this.setEvents();
}
});
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.6/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.6/dist/vuetify.min.js"></script>
<div id="app">
<v-app>
<v-navigation-drawer ref="drawer" app right hide-overlay :width="navigation.width" v-model="navigation.shown">
<v-toolbar color="primary">
<v-toolbar-title class="headline text-uppercase">
<span>t a</span><span class="font-weight-light"> b s </span>
</v-toolbar-title>
</v-toolbar>
<v-tabs>
<v-tab v-for="n in 3" :key="n">
Item {{ n }}
</v-tab>
<v-tab-item v-for="n in 3" :key="n">
<v-card flat>
<v-card-text>Content for tab {{ n }} would go here</v-card-text>
</v-card>
</v-tab-item>
</v-tabs>
</v-navigation-drawer>
<v-container>
<v-layout justify-center>
<v-btn #click="navigation.shown = !navigation.shown">Toggle {{ direction }}</v-btn>
</v-layout>
<v-layout justify-center>
<p>Once the navigation drawer is opened, drag it's border to resize (highlited in red)</p>
</v-layout>
</v-container>
</v-app>
</div>
Thats because of transition effect on navigation drawer. set transition to initial at mouse down, then release that on mouse up.
at mousedown add
el.style.transition ='initial';
at mouseup add
el.style.transition ='';
Codepen : https://codepen.io/dagalti/pen/ywRNYx

Vue components data and methods disappear on one item when rendered with v-for as Vuetify's cards

I have Vue component that renders a list of Vuetify cards:
<restaurant-item
v-for="card in userRestaurantCards"
:key="card['.key']"
:card="card"
>
</restaurant-item>
The card displays info obtained from props, Vuex, as well as info defined in the restaurant-item card itself:
<v-card>
<v-img
class="white--text"
height="200px"
:src="photo"
>
<v-container fill-height fluid class="card-edit">
<v-layout fill-height>
<v-flex xs12 align-end flexbox>
<v-menu bottom right>
<v-btn slot="activator" dark icon>
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<edit-restaurant-dialog :card="card" :previousComment="comment"></edit-restaurant-dialog>
<v-list-tile >
<v-list-tile-title>Delete</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</v-flex>
</v-layout>
</v-container>
</v-img>
<v-card-title>
<div>
<span class="grey--text">Friends rating: {{ card.rating }}</span><br>
<h3>{{ card.name }}</h3><br>
<span>{{ card.location }}</span>
</div>
</v-card-title>
<v-card-actions>
<v-btn flat color="purple">Comments</v-btn>
<v-spacer></v-spacer>
<v-btn icon #click="show = !show">
<v-icon>{{ show ? 'keyboard_arrow_down' : 'keyboard_arrow_up' }}</v-icon>
</v-btn>
</v-card-actions>
<v-slide-y-transition>
<v-card-text v-show="show">
<div> {{ comment.content }} </div>
</v-card-text>
</v-slide-y-transition>
</v-card>
The script is:
import { find, isEmpty } from 'lodash-es'
import { mapGetters } from 'vuex'
import EditRestaurantDialog from '#/components/dashboard/EditRestaurantDialog'
export default {
name: 'restaurant-item',
components: {
EditRestaurantDialog
},
props: {
card: Object
},
data() {
return {
show: false,
name: this.card.name,
location: this.card.location,
rating: this.card.rating,
link: this.card.link,
photo: this.getPhotoUrl()
}
},
computed: {
comment() {
// Grab the content of the comment that the current user wrote for the current restaurant
if (isEmpty(this.card.comments)) {
return { content: 'You have no opinions of this place so far' }
} else {
const userComment = find(this.card.comments, o => o.uid === this.currentUser)
return userComment
}
},
...mapGetters(['currentUser'])
},
methods: {
getPhotoUrl() {
const cardsDefault = find(this.card.photos, o => o.default).url
if (isEmpty(cardsDefault)) {
return 'https://via.placeholder.com/500x200.png?text=No+pics+here+...yet!'
} else {
return cardsDefault
}
}
}
}
Here is the kicker: when I have 2 objects in the data, the first card component renders correctly... while the second doesn't have any of the methods or data defined right there in the script.
Here's a link to a screenshot of the Vue Devtools inspecting the first card:
https://drive.google.com/file/d/1LL4GQEj0S_CJv55KRgJPHsCmvh8X3UWP/view?usp=sharing
Here's a link of the second card:
https://drive.google.com/open?id=13MdfmUIMHCB_xy3syeKz6-Bt9R2Yy4Xe
Notice how the second one has no Data except for the route?
Also, note that both components loaded props, vuex bindings and computed properties just as expected. Only the Data is empty on the second one...
I've been scratching my head for a while over this. Any ideas would be more than welcome.
I got it to work after I moved the method getPhotoUrl method to a computed property:
computed: {
comment() {
// Grab the content of the comment that the current user wrote for the current restaurant
if (isEmpty(this.card.comments)) {
return { content: 'You have no opinions of this place so far' }
} else {
const userComment = find(this.card.comments, o => o.uid === this.currentUser)
return userComment
}
},
photoUrl() {
const cardsDefault = find(this.card.photos, o => o.default)
if (isEmpty(cardsDefault)) {
return 'https://via.placeholder.com/500x200.png?text=No+pics+here+...yet!'
} else {
return cardsDefault.url
}
},
...mapGetters(['currentUser'])
}