How to pass props to third child in nuxt - vuejs2

ModalsComponent is being global to all my cards
This how I am calling CardComponent:
<CardComponent
v-for="card of cards"
:key="card.urlsId"
:cardImages="card.images"
:cardTitle="card.title"
:cardDescription="card.description"
:mediaRef="card.urlsId"
:dbRef="card.dbId"
:deleteBtn="true"
:imagesWithSlider="true"
:deleteModalOpen="deleteModalOpen"
#onOpenDeleteModal="
;(deleteModalOpen = true), (newCardModalOpen = false)
"
#onCloseDeleteModal="deleteModalOpen = false"
/>
And this is how my CardComponent looks like:
<template>
<div class="cards">
<ModalsComponent
v-if="deleteModalOpen"
:deleteModal="true"
#closeModal="$emit('onCloseDeleteModal')"
#onDeleteCard="log"
/>
<v-card class="card-container">
<div class="delete-btn">
<v-btn
v-if="deleteBtn"
class="mx-2"
fab
dark
small
#click="
$emit('onOpenDeleteModal'), (deletingCardRefs = { dbRef, mediaRef })
"
>
<v-icon dark> mdi-delete </v-icon>
</v-btn>
</div>
<ImageSlider
v-if="imagesWithSlider"
:imagesArray="cardImages"
:arrowBtns="false"
/>
<v-img v-else></v-img>
<div class="text-container">
<h3 class="card-title">{{ cardTitle }}</h3>
<p class="card-description">{{ cardDescription }}</p>
</div>
</v-card>
</div>
</template>
in CardComponent it is being looped after v-card element and my ModalsComponent being global to all my cards how to target it each of my cards separately?

Related

Vuetify 3 : v-menu location property not working

i have a v-menu on toolbars right corner. The menu displays as bottom right (end) so half the card is outside the view. I want to change to bottom left (start) however i can't seem to make it work.
<v-menu
location="start"
rounded
>
<template v-slot:activator="{ props }">
<v-btn
icon
v-bind="props"
>
<v-avatar
color="brown"
size="large"
>
<span class="white--text text-h5">{{ user.initials }}</span>
</v-avatar>
</v-btn>
</template>
<v-card>
<v-card-text>
<div class="mx-auto text-center">
<v-avatar
color="brown"
>
<span class="white--text text-h5">{{ user.initials }}</span>
</v-avatar>
<h3>{{ user.fullName }}</h3>
<p class="text-caption mt-1">
{{ user.email }}
</p>
<v-divider class="my-3"></v-divider>
<v-btn
rounded
variant="text"
#click="() => goSettings() "
>
Settings
</v-btn>
<v-divider class="my-3"></v-divider>
<v-btn
#click="() => logOut()"
>
Disconnect
</v-btn>
</div>
</v-card-text>
</v-card>
</v-menu>
I'm missing somethings? im checking the example in the docs https://next.vuetifyjs.com/en/components/menus/
thanks
edit: added screenshots of current behaviour vs expected
Edit 2: I tried the v-menu on a codepen and works as intended, however for some reason, it does not work inside a v-app-bar
Try using prop "anchor" instead of "location".
<v-menu
anchor="bottom end"
rounded
>
<template v-slot:activator="{ props }">
<v-btn
icon
v-bind="props"
>
<v-avatar
color="brown"
size="large"
>
<span class="white--text text-h5">{{ user.initials }}</span>
</v-avatar>
</v-btn>
</template>
<v-card>
<v-card-text>
<div class="mx-auto text-center">
<v-avatar
color="brown"
>
<span class="white--text text-h5">{{ user.initials }}</span>
</v-avatar>
<h3>{{ user.fullName }}</h3>
<p class="text-caption mt-1">
{{ user.email }}
</p>
<v-divider class="my-3"></v-divider>
<v-btn
rounded
variant="text"
#click="() => goSettings() "
>
Settings
</v-btn>
<v-divider class="my-3"></v-divider>
<v-btn
#click="() => logOut()"
>
Disconnect
</v-btn>
</div>
</v-card-text>
</v-card>
</v-menu>
I can't even tell you why this could work, because I wasn't able to find it in the Docs or Files, but it is used like that in one of the templates I'm using.
However, this only works for large screens, on mobile the card will be outside the view again.
I had the same problem, the solution is using the activator prop or perhaps, in your case you sould use the internal-activator prop.
<v-menu
location="start"
rounded
internal-activator
>
<template v-slot:activator="{ props }">
<v-btn
icon
v-bind="props"
>
<v-avatar
color="brown"
size="large"
>
<span class="white--text text-h5">{{ user.initials }}</span>
</v-avatar>
</v-btn>
</template>
<v-card>
<v-card-text>
<div class="mx-auto text-center">
<v-avatar
color="brown"
>
<span class="white--text text-h5">{{ user.initials }}</span>
</v-avatar>
<h3>{{ user.fullName }}</h3>
<p class="text-caption mt-1">
{{ user.email }}
</p>
<v-divider class="my-3"></v-divider>
<v-btn
rounded
variant="text"
#click="() => goSettings() "
>
Settings
</v-btn>
<v-divider class="my-3"></v-divider>
<v-btn
#click="() => logOut()"
>
Disconnect
</v-btn>
</div>
</v-card-text>
</v-card>
</v-menu>

v-date-picker customize it and have today, last 7 days beside it

Hi just got a question if this kind of thing is possible?
enter image description here
this is so far I have done.
<template>
<v-row align="center">
<v-checkbox
v-model="landscape"
label="Landscape"
></v-checkbox>
<v-date-picker
v-model="picker"
landscape
></v-date-picker>
</v-row>
</template>
I solved it using v-card. It was challenging one and been looking for the answer all over, I was like crashing my head on it. The output would be like this:
enter image description here
The complete code:
<template v-if="filters">
<div class="d-flex justify-lg-space-between filter__activities">
<v-text-field
v-model="searchInText"
outlined
dense
append-icon="fas fa-search"
placeholder="Search"
/>
<div class="px-2" />
<v-select
v-model="searchInSelect"
append-icon="fas fa-chevron-down"
item-color="lucky-point"
placeholder="Category"
outlined
dense
:items="types"
:menu-props="{ bottom: true, offsetY: true }"
class="lucky-point--text"
/>
</div>
<div class="filter__activities">
<v-menu
ref="menu1"
v-model="menu1"
:close-on-content-click="false"
transition="scale-transition"
offset-y
bottom
min-width="auto"
>
<template v-slot:activator="{ on }">
<v-text-field
:value="computedDateFormatted"
outlined
dense
placeholder="Select Date"
append-icon="mdi-calendar"
v-on="on"
/>
</template>
<v-card>
<div class="d-flex">
<div class="pa-2 py-16">
<div class="py-1">
<v-btn
plain
class="text-capitalize text-subtitle-1 mine-shaft--text filter__activities-active-btn"
>
Today
</v-btn>
</div>
<div class="py-1">
<v-btn
plain
class="text-capitalize text-subtitle-1 mine-shaft--text"
>
Last 7 days
</v-btn>
</div>
<div class="py-1">
<v-btn
plain
class="text-capitalize text-subtitle-1 mine-shaft--text"
>
Last 30 days
</v-btn>
</div>
<div class="py-1">
<v-btn
plain
class="text-capitalize text-subtitle-1 mine-shaft--text"
>
Last 90 days
</v-btn>
</div>
</div>
<span class="mx-2 mercury--bx-1"></span>
<div>
<v-date-picker
v-model="date"
#input="menu1 = false"
flat
no-title
color="lucky-point"
width="392"
/>
</div>
</div>
</v-card>
</v-menu>
</div>
</template>

Get value from v-item-group

I have the following v-item-group where a user can select a pre-defined amount or type himself a custom amount.
Here's the design of the v-item-group. However, I can't figure out how to get the value from Custom Amount. The property this.item is undefined. I thought I need to create another v-model but perhaps there is a simple and straignt-forward solution.
<v-item-group v-model="item">
<v-container>
<v-row>
<v-item v-for="n in amounts" :key="n" v-slot="{ active, toggle }">
<v-card
:color="active ? 'deep-purple accent-3' : 'grey'"
class="d-flex align-center rounded-circle mr-3"
dark
height="64"
width="64"
#click="toggle"
>
<v-scroll-y-transition>
<div v-if="active" class="h3 flex-grow-1 text-center">
{{ n }}
</div>
<div v-else class=" h5 flex-grow-1 text-center">
{{ n }}
</div>
</v-scroll-y-transition>
</v-card>
</v-item>
<v-item v-slot="{ toggle }" key="5">
<v-text-field
label="Custom Amount"
hide-details="auto"
#click="toggle"
></v-text-field>
</v-item>
</v-row>
</v-container>
</v-item-group>
Declare a local data property, and use v-model on v-text-field:
<v-text-field v-model="customAmount">
export default {
data() {
return {
customAmount: '2000'
}
}
}
The function that processes the user's selection could then get the custom value simply by this.customAmount.
demo

Is there a Vue or Vuetify component that does not render ANY output?

I have a custom navMenu component that I show twice on my page - once across the top, and once hidden in a v-navigation-drawer until the screen width gets small enough to show it:
<template>
<nav>
<v-app-bar app hide-on-scroll>
<template #extension v-if="$vuetify.breakpoint.smAndUp">
<v-container>
<v-row>
<v-spacer />
<navMenu :items="menuItems" />
<v-spacer />
</v-row>
</v-container>
</template>
<v-app-bar-nav-icon
#click="toggleDrawer()"
v-if="$vuetify.breakpoint.xs"
/>
<img id="logo"
alt="corporate logo"
src="#/assets/full_logo.svg"
width="200"
height="60"
/>
<v-spacer />
<h3 class="info--text headline">My Fancy Website</h3>
</v-app-bar>
<v-navigation-drawer app
v-model="drawer"
v-if="$vuetify.breakpoint.smAndDown">
<navMenu :items="menuItems" />
</v-navigation-drawer>
</nav>
</template>
NavMenu.vue
<template>
<v-col v-for="(item, index) in items" :key="index">
<div v-if="item.children">
<v-menu transition="slide-y-transition" bottom>
<template #activator="{ on }">
<v-btn text v-on="on">{{ item.label }}</v-btn>
</template>
<v-list>
<v-list-item
v-for="(child, j) in item.children"
:key="j"
router
:exact="child.exact"
:to="{ name: child.routeName }"
>
<v-list-item-title class="text-capitalize">
{{ child.label }}
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</div>
<div v-else>
<v-btn text router :to="{ name: item.routeName }" :exact="item.exact">
{{ item.label }}
</v-btn>
</div>
</v-col>
</template>
...you may have noticed a fatal flaw in my component: you can't iterate on a root element! Simple enough, wrap it in a <div />, right? Wrong. Wrapping the contents of the template in a div really screws up the layout of the menu items - it renders them stacked vertically instead of horizontally - I think the CSS is looking for a direct child or something.
Is there some alternative element that I can use for the template to satisfy the "one root element" edict that doesn't render any output? Oh, and I tried using the <template /> element already - you can't use it as a root element.
You were so close to finding the answer...
Actually, you should put in a div container, but then just change the display property of the container so the items are still positioned horizontally:
NavMenu.vue
<template>
<div style="display: flex">
<v-col v-for="(item, index) in items" :key="index">
...
I updated your code below. Essentially, all you need to do is to move the entire <v-navigation-drawer> component into your NavMenu.vue file and add the additional drawer prop. Since the <v-navigation-drawer component doesn't actually do much on its own. The #input event listener is only so that you can have the parent component update the drawer value outside of the child component.
<template>
<nav>
<v-app-bar app hide-on-scroll>
<template #extension v-if="$vuetify.breakpoint.smAndUp">
<v-container>
<v-row>
<v-spacer />
<navMenu :items="menuItems" />
<v-spacer />
</v-row>
</v-container>
</template>
<v-app-bar-nav-icon
#click="toggleDrawer()"
v-if="$vuetify.breakpoint.xs"
/>
<img id="logo"
alt="corporate logo"
src="#/assets/full_logo.svg"
width="200"
height="60"
/>
<v-spacer />
<h3 class="info--text headline">My Fancy Website</h3>
</v-app-bar>
<navMenu
v-if="$vuetify.breakpoint.smAndDown"
:drawer="drawer"
:items="menuItems"
#navInput="toggleDrawer()"
/>
</nav>
</template>
NavMenu.vue
<template>
<v-navigation-drawer app :value="drawer" #input="$emit('navInput')>
<v-col v-for="(item, index) in items" :key="index">
<div v-if="item.children">
<v-menu transition="slide-y-transition" bottom>
<template #activator="{ on }">
<v-btn text v-on="on">{{ item.label }}</v-btn>
</template>
<v-list>
<v-list-item
v-for="(child, j) in item.children"
:key="j"
router
:exact="child.exact"
:to="{ name: child.routeName }"
>
<v-list-item-title class="text-capitalize">
{{ child.label }}
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</div>
<div v-else>
<v-btn text router :to="{ name: item.routeName }" :exact="item.exact">
{{ item.label }}
</v-btn>
</div>
</v-col>
</v-navigation-drawer>
</template>
<script>
export default {
props: {
drawer: Boolean,
items: {
type: Array,
default: () => []
}
}
};
</script>

Vuetify - How can I use the Data-Table search feature to filter by a dynamically calculated field value?

Trying to use Vuetify's Data-Table to search/filter based on the computed value of a field. As feel free to jump into the codepen and type in some values for yourself. For example, I have it setup in such a way that the email address field can be searched by; however, the name of the employee and phone record fields are not functional.
Codepen
https://codepen.io/Jasilo/pen/PooLjbE
VUE:
<div id="app">
<v-app id="inspire">
<v-card>
<header>How can I search by the computed Name and Phone fields?</header>
<v-card-title>
<header>Employee List</header>
<v-spacer></v-spacer>
<v-text-field v-model="search" append-icon="search" label="Search" single-line hide-details></v-text-field>
</v-card-title>
<v-data-table v-bind:headers="headers" v-bind:items="employeesArray" v-bind:search="search">
<template v-slot:item.email="{ item }">
<div>
{{ item["email"] }} </div>
</template>
<template v-slot:item.name="{ item }">
<div>
{{ getName(item) }}
</div>
</template>
<template v-slot:item.phone="{ item }">
<div> {{ getPhone(item) }}</div>
</template>
<template v-slot:no-data>
<div icon="warning">
{{ gridEmpty }}
</div>
</template>
</v-data-table>
</v-card>
</v-app>
</div>
HTML:
<div id="app">
<v-app id="inspire">
<v-card>
<header>How can I search by the computed Name and Phone fields?</header>
<v-card-title>
<header>Employee List</header>
<v-spacer></v-spacer>
<v-text-field v-model="search" append-icon="search" label="Search" single-line hide-details></v-text-field>
</v-card-title>
<v-data-table v-bind:headers="headers" v-bind:items="employeesArray" v-bind:search="search">
<template v-slot:item.email="{ item }">
<div>
{{ item["email"] }} </div>
</template>
<template v-slot:item.name="{ item }">
<div>
{{ getName(item) }}
</div>
</template>
<template v-slot:item.phone="{ item }">
<div> {{ getPhone(item) }}</div>
</template>
<template v-slot:no-data>
<div icon="warning">
{{ gridEmpty }}
</div>
</template>
</v-data-table>
</v-card>
</v-app>
</div>
Simplest way is to use a computed property:
computed: {
employeeTableData() {
return this.employeesArray.map(e => {
return {
email: e.email,
name: this.getName(e),
phone: this.getPhone(e),
};
});
},
},
Then change v-data-table to use employeeTableData instead and directly reference the attributes.
Working codepen
You can then search XD or 666- and it will correctly filter on name and phone number.