Scrollable dropdown on nav item in Vue - vue.js

I am using Vue.js 2.6 and I have a tab reports.
I want to vertically scroll my report options when there are more than three options.
If it helps - all those b-dropdowns are translated to li's with anchors inside when I inspect those in the browser.
<template>
<b-navbar-nav>
<b-nav-item">
<router-link to="/logs" class="nav-link">General Logs</router-link>
</b-nav-item>
<b-nav-item-dropdown right class="nav-link">
<template slot="button-content">
<span>Reports</span>
</template>
<b-dropdown-item>Foo</b-dropdown-item>
<b-dropdown-item>Bar</b-dropdown-item>
<b-dropdown-item>Foo2</b-dropdown-item>
<b-dropdown-item>Bar2</b-dropdown-item>
<b-dropdown-item>Foo3</b-dropdown-item>
<b-dropdown-item>Bar3</b-dropdown-item>
</b-nav-item-dropdown>
</b-navbar-nav>
</template>

try this:
.navbar-nav .dropdown-menu {
overflow: auto;
height: 100px;
}

Related

Text-color for v-autocomplete

I have a v-autocomplete that only displays after I click on a loop button in my navbar.
My application is supposed to allow the search on actors. I have a placeholder on this autocomplete and I'd like to style the appearance of it.
At the moment it is black and in regular font, I'd like it white in italic but since I can't inspect the element I can't know which class to edit in the css.
Here's my code:
<template>
<div class="inspire">
<v-app-bar style="padding: 10px 0px;"
color="rgba(33,33,33,255)"
elevation="0"
height="64px"
>
<div style="width:100%" v-if="$route.name == 'Mapping'">
<template>
<v-autocomplete
v-model="valuesActor"
placeholder="Search on actors"
:items="actorArray"
:search-input.sync="searchActor"
filled
autofocus
mutliple
#blur="toggleSearch"
background-color="#313131"
append-icon=""
prepend-inner-icon="mdi-arrow-left"
color="var(--textLightGrey)"
:menu-props="{maxWidth: 1600}"
>
</v-autocomplete>
</template>
</div>
</v-app-bar>
</div>
</template>
You can style it like this-
<style scoped>
>>> ::placeholder {
color: white !important;
font-style: italic !important;
}
</style>
color props of the vuetify v-autocomplete component shoud be a string. https://vuetifyjs.com/en/api/v-autocomplete/#props-color
So either use material color name or css color in this color props field, or use style directive style="'color:var(--textLightGrey);'".
You could also use vuetify class heler: https://next.vuetifyjs.com/en/styles/colors/

How to conditionally render multiple components based on route without affecting layout in vue3

I have a navbar and two side menus which I use in multiple pages. But for a number of pages I don't want to have the side menu.
I have tried using v-if with $router.name, but because I was using a grid system, the layout would break. Then also it was impossible to add more than one component to not render the side menus.
This is the template:
<template>
<TheNavbar/>
<div class="container">
<TheLeftMenu/>
<router-view/>
<TheRightMenu/>
</div>
</template>
My solution to avoid the grid system to squash the router-view component was to divide the template in two, one using the sidemenus, the other without them.
Then in order to have multiple pages to not load the side menus I used a computed property to hold an array with all the routes to not render the side menus:
<template>
<div v-if="blockedRoutes.includes($route.name) == false">
<TheNavbar/>
<div class="container">
<TheLeftMenu/>
<router-view/>
<TheRightMenu/>
</div>
</div>
<div v-else>
<TheNavbar/>
<router-view/>
</div>
</template>
computed: {
blockedRoutes () {
return ['Register', 'SignIn', 'About']
}
}
you can use the simple method of a flex container;
<template>
<router-view v-slot="{ Component, route }">
<div class="holder">
<div>
<TheLeftMenu/>
</div">
<div class="main">
<transition name="fade" mode="out-in"><component :is="Component" /></transition>
</div>
<div v-if="!route.meta.hideRmenu">
<TheRightMenu/>
</div>
</div>
</router-view>
</template>
<style>
.holder{
display : flex;
width : 100%;
/*if you want your container not to grow with the page do the following*/
overflow: hidden;
height : 100vh;
}
.holder .main{
flex : 1;
flex-direction: row;
/*if you want your container not to grow with the page do the following*/
max-height : 100vh;
overflow : auto;
}
.holder :not(.main){
min-width: 32px;
}
</style>
This way you can, if you want, also add transitions.
If you don't want to use transitions, you just need to remove the transitions tags.
This aproach uses is focused for Vue 3 and uses Scoped Slots

How to make modal popup window in Vuejs?

<style src="./LoginButton.scss" lang="scss"></style>
<i18n src="./LoginButton.txt"></i18n>
<script src="./LoginButton.js"></script>
<template>
<div class="header-login component-same ml-10">
<span v-if="showLoggedIn">
<router-link :to="{ name: 'user' }" data-test="login-info-name">
<i class="dl-icon-user12"></i>
<span class="target-text hidden-xs hidden-sm">{{
$t('myAccount')
}}</span>
</router-link>
</span>
<!-- <span v-if="showLoggedIn" class="hidden-xs">
<a #click="logout" data-test="logout-button">
<span>{{ $t("signOut") }}</span>
</a>
</span>-->
<span v-else data-test="login-button">
<router-link :to="{ name: 'login' }">
<i class="dl-icon-user12"></i>
<span class="target-text hidden-xs hidden-sm">{{ $t('Register') }}</span>
</router-link>
</span>
</div>
</template>
I have written the above code for login, Where in this particular line
User has a register button, As soon as the user clicks on the register button, the User will be redirected to another page where he can fill up the basic details, So Instead of redirecting into another page, I want the Register button as a Popup, wherein the popup user can enter details.
also, I tried bootstarp-vue but I wasn't able to find the solution.
It's easier than what you think and mostly you won't need a special CSS lib for that, so the thing to do is just to make another component and call it whatever you want(but modal.vue makes sense here):
//inside modal.vue:
<template>
<div className="modal__wrapper">
<div className="modal">
<slot/>
</div>
</div>
</template>
<style lang="scss" scoped>
.modal{
width: 300px;
height: 100px;
border-radius: 10px;
background-color: white;
padding: 20px 20px;
z-index: 1200;
&__wrapper{
background-color: rgba(0,0,0,0.4);
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
position: absolute;
top: o;
}
}
</style>
in its simplest form, it's just a component with some styling to make it look like a modal (a transparent background(to make it look it's over the previous page) and an absolute position for its wrapper(the transparent one) and some centering techniques for its actual content),I didn't put any script in it(because it's just a simple modal I'm showing you to give the idea how to make yours) and then there is this slot part meaning you can pass your registration form to this modal component, from your parent component and use a boolean flag to just show it on register click
(sure you might need to add some more CSS to the .modal class):
<i18n src="./LoginButton.txt"></i18n>
<script src="./LoginButton.js"></script> <!-- the cleaner thing would
be to import them in your script section somehow -->
<template>
<div class="header-login component-same ml-10">
<span v-if="showLoggedIn">
<router-link :to="{ name: 'user' }" data-test="login-info-name">
<i class="dl-icon-user12"></i>
<span class="target-text hidden-xs hidden-sm">{{
$t('myAccount')
}}</span>
</router-link>
</span>
<span v-else data-test="login-button">
<!-- no need to rerouting to another path -->
<Modal>
<!--your template for registration will go here-->
<i class="dl-icon-user12"></i>
<span class="target-text hidden-xs hidden-sm">{{ $t('Register') }}</span>
</Modal>
</span>
</div>
</template>
//you gotta import the modal component so in your script section you have sth like this(BTW what type of structure are you using for your project? are you using vue-cli's scaffold or what? Are you using babel? cuz I'm gonna assume you are!)
<script>
import Modal from 'The_Relative_Path_to_the_Modal_you_just_created';
export default {
components:{
Modal
},
data(){
return{
showLoggedIn: false
}
}
}
</script>
<style src="./LoginButton.scss" lang="scss"></style>

How to make an append item always visible in v-select vuetify

I have a vuetify v-select dropdown.
Inside I made a slot #append-item in which I have a button "validate"
I want the button to always be visible when I scroll inside the dropdown.
Wrap your button with a div having the append class name :
<template #append-item>
<div class="append">
<v-btn color="primary">valider</v-btn>
</div>
</template>
that class should have the following css rules :
.append{
position:sticky;
bottom:8px;
width:100%;
display:flex;
justify-content :center;
background :white;
}
LIVE DEMO
I added this style to my "validate" button and it worked:
.append {
position: sticky;
bottom: 0;
background: white;
}
<template #append-item>
<div class="append">
<v-btn color="primary">
Validate
</v-btn>
</div>
</template>

VuetifyJS vertical button text

I'd like to have text below the icon in a v-btn and can't seem to find how to do this. How is this possible?
To achieve this look with Vuetify, you just need to overwrite the flex direction in the v-btn__content class. Don't forget to give a unique class (for me flexcol) to your button so the style change won't affect other Vuetify buttons.
<template>
<v-btn class="flexcol" icon height="100" width="100">
<v-icon> mdi-tools </v-icon>
<span> Tools </span>
</v-btn>
</template>
<style>
.flexcol .v-btn__content {
flex-direction: column;
}
</style>
You don't really need vuetify to do that.
You can just use css and flexbox.
Say you have:
<div class="wrapper">
<div>Text Above</div>
<div>Text Below</div>
</div>
You want the "Text Below" to stand below the "Text Above".You can do it like this:
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
}
However click here to see your solution
Try this
<div class="d-flex flex-column align-center">
<v-btn icon height="30">
<v-icon>mdi-history</v-icon>
</v-btn>
<p class="mb-0">abc</p>
</div>