custom navigation for q-carousel not working - vue.js

I am struggling solving my navigation q-carousel that I want, it is does not work.
It just shows default navigation only but not the custom one that I grab the code from the Quasar website.
My template:
<q-card-section class="q-pa-none" >
<div style="width:60%; padding-bottom: 250px"
class="bg-transparent text-center q-gutter-y-lg absolute-center ">
<q-carousel
animated
v-model="slide"
arrows
navigation
infinite
control-type="flat"
control-color="secondary"
class="bg-transparent text-center">
>
<template v-slot:navigation-icon="{ active, btnProps, onClick }">
<q-btn v-if="active" size="lg" icon="home" color="yellow" flat round dense #click="onClick" />
<q-btn v-else size="sm" :icon="btnProps.icon" color="white" flat round dense #click="onClick" />
</template>
<q-carousel-slide :name="1" >1</q-carousel-slide>
<q-carousel-slide :name="2">2</q-carousel-slide>
<q-carousel-slide :name="3">3</q-carousel-slide>
</q-carousel>
</q-card-section>
My script:
export default {
data() {
return {
slide : 1,
}
}
}

Your code is actually working, but you kind of mixed opening and closing tags.
There is no open tag for </q-card-section>
There is no closing tag for your leading <div>
The below code should work for you:
<div
style="width: 60%; padding-bottom: 250px"
class="bg-transparent text-center q-gutter-y-lg absolute-center"
>
<q-carousel
animated
v-model="slide"
arrows
navigation
infinite
control-type="flat"
control-color="secondary"
class="bg-transparent text-center"
>
<template v-slot:navigation-icon="{ active, btnProps, onClick }">
<q-btn
v-if="active"
size="lg"
icon="home"
color="yellow"
flat
round
dense
#click="onClick"
/>
<q-btn
v-else
size="sm"
:icon="btnProps.icon"
color="white"
flat
round
dense
#click="onClick"
/>
</template>
<q-carousel-slide :name="1">1</q-carousel-slide>
<q-carousel-slide :name="2">2</q-carousel-slide>
<q-carousel-slide :name="3">3</q-carousel-slide>
</q-carousel>
</div>
You should consider setting up auto formatting in your code editor/IDE to auto format your source code, if you are using VS Code you can do this quite easily: https://stackoverflow.com/a/29973358/13765033
This way, you shouldn't run into such trouble again (it also helps Stack Overflow users to read your source code).

Related

Vue tabs multiple of same child component type wrong data

I have tabs which display forms. There are different types of forms, and each type of form can be open in its own tab 0 to X times. The issue is specifically when there are more than one of the same type of form open, plus at least one other type open:
In this scenario, when I change from Item Two back to Item One, the form shows the name prop from Item Two.
Here's how the tabs are setup:
<v-tabs
dark
background-color="blue-grey darken-4"
show-arrows
height="30"
v-model="activeModel"
class="fixed-tabs-bar"
v-if="openTabs.length"
>
<v-tabs-slider color="accent"></v-tabs-slider>
<v-tab v-for="item in openTabs" :key="item.id" class="pr-0 white--text" color="accent" active-class="" #click="setActiveTab(item)">
<template class="white--text text-capitalize">
<v-icon>
{{ item.icon }}
</v-icon>
{{ item.name }}
<div v-if="item.changes">*</div>
<v-btn plain width="10" class="px-0" #click="closeTab(item.id)">
<v-icon dark small width="10">mdi-close</v-icon>
</v-btn>
</template>
</v-tab>
</v-tabs>
<v-tabs-items v-model="activeModel" style="background-color: #232323;">
<v-tab-item v-for="item in openTabs" :key="item.id" style="height: 100%" :transition="false" eager>
<BlockForm
:key="item.id"
v-if="activeTab.type === 'blocks' && item.type === 'blocks'"
:name="openTabs[activeModel].name"
:activeProject="activeProject"
/>
<ItemForm :key="item.id" v-if="activeTab.type === 'items' && item.type === 'items'" :name="openTabs[activeModel].name" :projectName="activeProject" />
... More form types ...
</v-tab-item>
</v-tabs-items>
And set looks like:
setActiveTab: function(item) {
this.activeTab = item;
this.activeType = item.type;
}
The name prop is specifically what is wrong in the data.
<v-tab-item v-for="item in openTabs" :key="item.id" style="height: 100%" :transition="false" eager>
<BlockForm
:key="item.id"
v-if="activeTab.type === 'blocks' && item.type === 'blocks'"
:name="openTabs[activeModel].name"
:activeProject="activeProject"
/>
<ItemForm :key="item.id" v-if="activeTab.type === 'items' && item.type === 'items'" :name="openTabs[activeModel].name" :projectName="activeProject" />
... More form types ...
</v-tab-item>
The main problem is that when you set the activeTab variable, the v-tab-item element is not re-rendered. Because you are using item-id as key. You can use nextTick or directly apply the solution below.
You can take a look at Vue reactivity
:key="`${activeTab.id}-${item.id}`"

Hello everyone, i need some help to implement a show more button with quasar and vuejs

I have this part of code, i need add the action to show more or less the text.
<q-card
class="my-card text-white"
style="background: radial-gradient(circle, #229954 20%, #014a88 90%)"
>
<q-card-section>
<div class="text-h6">{{ titulo }}</div>
</q-card-section>
<q-card-section class="q-pt-none">
{{ traducir}}
</q-card-section>
<q-card-actions>
<q-btn flat label="Show More" />
</q-card-actions>
</q-card>
first you add the clickevent that calls a method called toggleText then add a conditional v-if to the section you want to toggle
<q-card
class="my-card text-white"
style="background: radial-gradient(circle, #229954 20%, #014a88 90%)"
>
<q-card-section>
<div class="text-h6">{{ titulo }}</div>
</q-card-section>
<q-card-section v-if="showText" class="q-pt-none">
{{ traducir}}
</q-card-section>
<q-card-actions #click="toggleText">
<q-btn flat label="Show More" />
</q-card-actions>
</q-card>
then you create the boolean varibale that will be used in our v-if condition
then create the toggleText method that toggles the boolean value.
<script>
export default {
name: 'showmore',
data () {
return {
showText: false,
}
},
methods: {
toggleText () {
this.showText = !this.showText;
}
}
}
</script>

How to change Layout of Quasar App and put the left Drawer to the right?

I am lost with the layout of Quasar and don't understand it, although I've read the documentation of it.
The scaffolder gave me the following code. But this makes the Drawer on the left side. How can I put it to the right side?
<template>
<q-layout view="lHh Lpr lFf">
<q-header elevated>
<q-toolbar>
<q-btn
flat
dense
round
icon="menu"
aria-label="Menu"
#click="leftDrawerOpen = !leftDrawerOpen"
/>
<q-toolbar-title>
Quasar App
</q-toolbar-title>
<div>Quasar v{{ $q.version }}</div>
</q-toolbar>
</q-header>
<q-drawer
v-model="leftDrawerOpen"
show-if-above
bordered
content-class="bg-grey-1"
>
<q-list>
<q-item-label
header
class="text-grey-8"
>
Essential Links
</q-item-label>
<EssentialLink
v-for="link in essentialLinks"
:key="link.title"
v-bind="link"
/>
</q-list>
</q-drawer>
<q-page-container>
<router-view />
</q-page-container>
</q-layout>
</template>
I thought it has something to do with the letters in
However. Playing with them won't change anything.
I also tried to put the q-drawer-tag below the q-page-container, with no luck either.
How to make the drawer visible on the right side?
you can set the behavior to side="right"
https://quasar.dev/layout/drawer#QDrawer-API
<q-drawer
v-model="leftDrawerOpen"
side="right"
show-if-above
bordered
content-class="bg-grey-1"
>
<q-list>
<q-item-label header class="text-grey-8">
Essential Links
</q-item-label>
<EssentialLink
v-for="link in essentialLinks"
:key="link.title"
v-bind="link"
/>
</q-list>
</q-drawer>

VueJS dynamic adding form components

I'm trying to make dynamic form, so if i want to add another text or some other field i can do it through web and save that to some json file.
Here is my code so far:
<template>
<div class="q-pa-md" style="max-width: 800px">
<div class="col-2">
<q-btn color="primary" label="Add Field" #click="addField = true"/>
</div>
<q-dialog v-model="addField">
<q-card>
<q-card-section>
<div class="text-h6">Add Field</div>
</q-card-section>
<q-separator />
<q-card-section style="max-height: 50vh" class="scroll">
test
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn flat label="Cancel" color="primary" v-close-popup />
<q-btn flat label="Add" color="primary" v-close-popup />
</q-card-actions>
</q-card>
</q-dialog>
<q-separator spaced inset />
<q-list>
<q-item>
<q-item-section>
<s-input v-model="data.email" label="Email" required />
<q-item-label caption lines="2">Email field.</q-item-label>
</q-item-section>
<q-item-section side top>
<div>
<q-toggle
v-model="data.active"
checked-icon="check"
color="blue"
unchecked-icon="clear"
/>
<q-icon name="keyboard_arrow_up" color="blue" size="md"/>
<q-icon name="keyboard_arrow_down" color="blue" size="md"/>
</div>
</q-item-section>
</q-item>
<q-separator spaced inset />
<q-item>
<q-item-section>
<s-input v-model="data.username" label="Username" required />
<q-item-label caption lines="2">Username field.</q-item-label>
</q-item-section>
<q-item-section side top>
<div>
<q-toggle
v-model="data.active"
checked-icon="check"
color="blue"
unchecked-icon="clear"
/>
<q-icon name="keyboard_arrow_up" color="blue" size="md"/>
<q-icon name="keyboard_arrow_down" color="blue" size="md"/>
</div>
</q-item-section>
</q-item>
<q-separator spaced inset />
<q-item>
<q-item-section>
<s-input v-model="data.password" label="Password" type="password" required />
<q-item-label caption lines="2">Password field.</q-item-label>
</q-item-section>
<q-item-section side top>
<div>
<q-toggle
v-model="data.active"
checked-icon="check"
color="blue"
unchecked-icon="clear"
/>
<q-icon name="keyboard_arrow_up" color="blue" size="md"/>
<q-icon name="keyboard_arrow_down" color="blue" size="md"/>
</div>
</q-item-section>
</q-item>
</q-list>
</div>
</template>
<script>
export default {
data () {
return {
newItem: true,
titleAction: null,
title: null,
titleHideEvent: false,
addField: false,
data: {
active: true
}
}
}
}
</script>
these are all field i have. Now if user wants to add another checkbox he should open dialog with button Add Field and choose that type of component and after he confirm that new chekcbox should be added in form. But i don't know how to make it dynamic. This 3 field should be mandatory and show in all forms (email, username and password).
Can anyone please help with some advice about this?
That's a huge template you got ^^"
Think that you can success by adding counters in your component's data.
Each time the User want to add a checkbox, you increment one of your counter depending on his choices. If the User wants to add a field for name for example, increment counterOfNameFields. In your template you can loop over these counters to display the right amount of fields.
Also, make a function that will push the content of these fields in arrays for example. You should have the same amount of arrays as counters.
Hope this answer your problem, tell me if it's not the case :)
You can have a list for added fields
data: function {
return {
...
addedItems:[],
...
}
}
And in your template
<q-item v-for="item in addedItems>
some html, which depends on how you define your items in your code
</q-item>
When you add an item to the page you just push it into
addedItems
collection and when you remove it from the page you remove it from collection.
I think this may be helpful https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components
You can use v-bind:is="'yourComponentName'"
And you can store list of dynamic components and their options in some array.
Something like this (of course it's only example)
<component v-for="component in components" v-bind:is="component.name" v-bind:someoptions="component.options">
</component>

Vuetify: show tooltip with a condition

I'm new to Vue.js and I hope with your help to understand scoped slots...
I would like to optimize my code, the tooltip must be visible on hover only if the label has more than 10 characters (or any other condition).
This works, but it is not optimized:
<v-btn>
<v-tooltip right v-if="slot.label.length > 20">
<template v-slot:activator="{on}">
<span class="text-truncate ml-1 mr-1" v-on="on">
{{slot.label}}
</span>
</template>
<span>{{slot.label}}</span>
</v-tooltip>
<span v-else class="text-truncate ml-1 mr-1">
{{slot.label}}
</span>
</v-btn>
I think the easiest way to achieve the desired effect without duplication is to use the disabled prop of v-tooltip.
new Vue({
el: '#app',
data () {
return {
slot: {
label: 'Label'
}
}
}
})
<link rel="stylesheet" href="https://unpkg.com/vuetify#1.5.16/dist/vuetify.css">
<script src="https://unpkg.com/vue#2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify#1.5.16/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-btn>
<v-tooltip right :disabled="slot.label.length < 10">
<template v-slot:activator="{on}">
<span class="text-truncate ml-1 mr-1" v-on="on">
Button: {{ slot.label }}
</span>
</template>
<span>Tooltip: {{ slot.label }}</span>
</v-tooltip>
</v-btn>
<v-btn #click="slot.label = 'Label'">Short</v-btn>
<v-btn #click="slot.label = 'Label label'">Long</v-btn>
</v-app>
</div>
The downside of this approach is that it still creates the tooltip even if it's disabled. The overhead isn't significant but if there are going to be a lot of tooltips then that might be a consideration.
There are various other ways to approach this but I can't think of any that are particularly simple. You could use a render function. That would allow you to write exactly what you want without any duplication but at the expense of needing to maintain a render function.
Sometimes you may want to show the tooltip when the underlying element is disabled. For eg: If a user has used all the resources in his account and then we need to ask the user to buy more resources. In such time insert an extra div and then add v-on onto to it.
<v-tooltip bottom :disabled="!noCandies">
<template v-slot:activator="{ on, attrs }">
<div v-on="on"> <!-- CREATE A DIV AND ADD V-ON HERE-->
<v-btn :disabled="noCandies" small class="mt-1" #click="useCandy">
Use candy
</v-btn>
</div>
</template>
<span>Buy more candies</span>
</v-tooltip>