implement user avatar composed with dropdown using BootstrapVue - vuejs2

I'm using Vue2 and styled with BootstrapVue
What I want to implement looks like below:
However, I tried myself and even looked up example in document ,
I have no idea why the result is vertical align(I thought it would be horizontal align by default).
Here's part of my html code
<b-navbar-nav>
<b-nav-item-dropdown text="User" left clas="user">
<template #button-content>
<div class="profile">
<b-icon icon="person-fill"></b-icon>
</div>
<p>Username</p>
</template>
<b-dropdown-item>
<router-link to="/login">Login</router-link>
</b-dropdown-item>
<b-dropdown-item>
<router-link to="/register">Register</router-link>
</b-dropdown-item>
<b-dropdown-item>
<router-link to="/logout">Logout</router-link>
</b-dropdown-item>
</b-nav-item-dropdown>
</b-navbar-nav>
jsfiddle

To fix it you need to wrap your content in b-row so that it won't overflow. This is working for me:
<b-nav-item-dropdown text="User" left clas="user" no-caret>
<template #button-content>
<b-row>
<div class="profile">
<b-icon icon="person-fill"></b-icon>
</div>
<p>Username</p>
<b-icon icon="caret-down-fill"></b-icon>
</b-row>
</template>
<b-dropdown-item>
<router-link to="/login">Login</router-link>
</b-dropdown-item>
<b-dropdown-item>
<router-link to="/register">Register</router-link>
</b-dropdown-item>
<b-dropdown-item>
<router-link to="/logout">Logout</router-link>
</b-dropdown-item>
</b-nav-item-dropdown>

Related

Bootstrap Vue b-table displaying nested object

I'm trying to list the drivers in b-table.
This gives me the correct name of the driver:
console.log(this.orders[0].order_drivers[0].populated_driver.user.username)
But when I want to display it on the table, it gives "data.item.order_drivers[0] is not defined" error.
Here's my code:
<b-table :items="orders"
:fields="fields"
:per-page="perPage"
:current-page="currentPage"
:filter="filter"
:filter-function="filterDate"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
sort-icon-left
small
>
<template #cell(status)="data">
<div class="text-nowrap">
<span class="align-text-top text-capitalize">{{ data.item.status }}</span>
</div>
</template>
<template #cell(order_number)="data">
<div class="text-nowrap">
<span class="align-text-top text-capitalize">{{ data.item.order_number}}</span>
</div>
</template>
<template #cell(deliver_date)="data">
<span class="align-text-top text-capitalize">{{ data.item.deliver_date }}</span>
</template>
<template #cell(pickup_date)="data">
<span class="align-text-top text-capitalize">{{ data.item.pickup_date }}</span>
</template>
<template #cell(subtotal)="data">
<div class="text-nowrap">
<span class="align-text-top text-capitalize">{{ data.item.subtotal }}</span>
</div>
</template>
<template #cell(tip)="data">
<div class="text-nowrap">
<span class="align-text-top text-capitalize">{{ data.item.tip_from_restaurant }}</span>
</div>
</template>
<template #cell(additional_tip)="data">
<div class="text-nowrap">
<span class="align-text-top text-capitalize">{{ data.item.extra_tip_from_restaurant }}</span>
</div>
</template>
<template #cell(tfr_tip)="data">
<div class="text-nowrap">
<span class="align-text-top text-capitalize">{{ data.item.tip_from_tfr }}</span>
</div>
</template>
<template #cell(tfr_additional_tip)="data">
<div class="text-nowrap">
<span class="align-text-top text-capitalize">{{ data.item.extra_tip_from_tfr }}</span>
</div>
</template>
<template #cell(driver)="data">
<div class="text-nowrap">
<span class="align-text-top text-capitalize">{{ data.item.order_drivers[0].populated_driver.user.username}}</span>
</div>
</template>
</b-table>
And this is what axios returns:
Response
UPDATE:
I've added v-if and v-else as suggested and worked for me!
<div class="text-nowrap">
<span class="align-text-top text-capitalize" v-if="orders[data.index].order_drivers.length!==0" >{{ data.item.order_drivers[0].populated_driver.user.username}}</span>
<span class="align-text-top text-capitalize" v-else>None.</span>
</div>

add an icon next to each row in the table using bootstrap vue?

I have a table that uses bootstrap Vue's table. Each row of the table corresponds to an item. My current problem is I need to add an icon next to each row, and display them every time I hover over that row, and then do some function when I click on this icon. But I can't find a way to add an icon. I have tried following the instructions on https://bootstrap-vue.org/docs/components/table with using slots but it only works for #head and #cell. Need an idea on this issue. This is my code and a picture describe my problem
<b-table
ref="table"
class="minh--30 mh--100 overflow-y-auto"
bordered
responsive
:items="items"
:fields="fields"
>
<template #head()="data">
<span>{{ $t(data.field.label) }}</span>
</template>
<template #cell(field)="data">
<span
v-if="data.item.isDrag"
class="d-block p-3"
>{{ data.item.field }}</span>
<b-dropdown
v-else
right
no-caret
variant="white"
class="minw--40 w-100"
menu-class="w-100 mh--24 overflow-auto minw-unset"
>
<template #button-content>
<div
class="flex-center minh--11 text-normal position-relative px-2"
>
<span class="pr-5 word-break text-line-clamp-1">{{ data.item.field }}</span>
<i
class="fas fa-chevron-down position-absolute top-50 end--1 translate-middle-y px-2"
/>
</div>
</template>
<b-dropdown-item
v-for="item in listField"
:key="item.id"
variant="normal py-2"
class="fs-12 fs-xl-15"
#click="selectField(item, data)"
>
<span class="word-break text-line-clamp-1">{{ $t(item.text) }}</span>
</b-dropdown-item>
</b-dropdown>
</template>
<template #cell(action)="data">
<b-dropdown
right
no-caret
variant="white"
class="minw--40 w-100"
menu-class="w-100 mh--24 overflow-auto minw-unset"
>
<template #button-content>
<div
class="flex-center minh--11 text-normal position-relative px-2"
>
<span class="pr-5 word-break text-line-clamp-1">{{ data.item.action }}</span>
<i
class="fas fa-chevron-down position-absolute top-50 end--1 translate-middle-y px-2"
/>
</div>
</template>
<b-dropdown-item
v-for="item in listDropdown"
:key="item.id"
variant="normal py-2"
class="fs-12 fs-xl-15"
#click="selectItem(item, data)"
>
<span class="word-break text-line-clamp-1">{{ $t(item.text) }}</span>
</b-dropdown-item>
</b-dropdown>
</template>
<template #cell(selectCharacter)="data">
<b-dropdown
right
no-caret
variant="white"
class="minw--40 w-100"
menu-class="w-100 mh--24 overflow-auto minw-unset"
>
<template #button-content>
<div
class="flex-center minh--11 text-normal position-relative px-2"
>
<span class="pr-5 word-break text-line-clamp-1">{{ data.item.selectCharacter }}</span>
<i
class="fas fa-chevron-down position-absolute top-50 end--1 translate-middle-y px-2"
/>
</div>
</template>
<b-dropdown-item
v-for="item in listCharacter"
:key="item.id"
variant="normal py-2"
class="fs-12 fs-xl-15"
#click="selectCharacter(item, data)"
>
<span class="word-break text-line-clamp-1">{{ $t(item.text) }}</span>
</b-dropdown-item>
</b-dropdown>
</template>
<template #cell(inputCharacter)="data">
<input
v-model="data.item.inputCharacter"
type="text"
class="form-control h--11 border-0"
>
</template>
<template #cell(startPosition)="data">
<input
v-model="data.item.startPosition"
type="number"
class="form-control h--11 border-0"
>
</template>
<template #cell(characterCount)="data">
<input
v-model="data.item.characterCount"
type="number"
class="form-control h--11 border-0"
>
</template>
<template #cell(needReplace)="data">
<input
v-model="data.item.needReplace"
type="text"
class="form-control h--11 border-0"
>
</template>
<template #cell(replace)="data">
<input
v-model="data.item.replace"
type="text"
class="form-control h--11 border-0"
>
</template>
<template #cell(delete)="data">
<div class="flex-center pt-1">
<input
v-if="!data.item.isDrag"
v-model="data.item.delete"
type="checkbox"
>
</div>
</template>
</b-table>
Based on reading the documentation, the table component wasn't designed for this use case because you are adding icons that are outside of the table itself.
One alternative would be to use the grid system https://bootstrap-vue.org/docs/components/layout#layout-and-grid-system to create one narrow column on the left for the icons and one wide column on the right for the table. In the narrow column, you could create rows that are exactly the height of each row of the table so that the items stay aligned with each row.
Another alternative would be to use the #cell slot, and put an element inside that uses CSS, possibly the transform property (https://www.w3schools.com/cssref/css3_pr_transform.asp), to make the element appear to the left of where it really is.

v-if="this.canupdate == true" not working

In vue I have a property this.canupdate.
My code looks like
<template v-if="this.canupdate == true">
<template v-if="row.item.edit">
<b-button variant="success" size="sm" #click="saveprestatierij(row.item, row.index)">
<i class="fas fa-save"></i>
</b-button>
</template>
<template v-else>
<b-button variant="primary" size="sm" #click="toggleeditprestatierij(row.item)">
<i class="fas fa-edit"></i>
</b-button>
</template>
</template>
But when I run the code, the block is not displaying, even if this.canupdate has a true value.
Anybody who sees where I'm wrong?
Kind regards,
Tim
Remove this from if-statement:
<template v-if="canupdate === true">
Or you can write like this:
<template v-if="canupdate">

How to hide navbar when collapsed in bootstrap-vue

I use bootstrapvue and I seek CSS only solution for hiding a text in navbar, when collapsed. I found .d-none .d-sm-block but they have no effect when toggler collapses the navigation. I found only jQuery solutions but they will not work with vue wrapper of bootstrap.
<b-navbar toggleable="sm" type="dark" variant="dark">
<b-navbar-brand href="/">
<img src="./assets/logo.png" :alt="$t('app.logo-alt')" class="d-inline-block align-top">
</b-navbar-brand>
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
<b-collapse id="nav-collapse" is-nav>
<b-navbar-nav class="d-inline-flex flex-column .d-none .d-sm-block">
<h2><b-nav-text class="text-white">{{ $t('app.name') }}</b-nav-text></h2>
<b-nav-text class="text-white">{{ $t('app.slogan') }}</b-nav-text>
</b-navbar-nav>
<b-navbar-nav class="ml-auto">
<b-nav-item-dropdown v-if="authorized" toggle-class="text-warning" right>
<template v-slot:button-content>
<b-icon-person-fill font-scale="2"></b-icon-person-fill>
</template>
<b-dropdown-item :to="{ name: 'user-profile', params: { id: userId } }">{{ $t('app.my-profile') }}</b-dropdown-item>
</b-nav-item-dropdown>
<b-nav-item-dropdown v-if="authorized" toggle-class="text-warning" right>
<template v-slot:button-content>
<b-icon-info font-scale="2"></b-icon-info>
</template>
<b-dropdown-item :to="{ name: 'help'}">{{ $t('app.help') }}</b-dropdown-item>
</b-nav-item-dropdown>
</b-navbar-nav>
</b-collapse>
</b-navbar>
This is the solution. Probably some conflict with flex model.
<b-collapse id="nav-collapse" is-nav>
<b-navbar-nav class="d-none d-sm-block">
<div class="d-inline-flex flex-column">
<h2><b-nav-text class="text-white">{{ $t('app.name') }}</b-nav-text></h2>
<b-nav-text class="text-white">{{ $t('app.slogan') }}</b-nav-text>
</div>
</b-navbar-nav>

Vue.js, vuetify.js Accordion do not open

I have a custom component blog and with an accordion (from vuetify.js) I show the posts in the blog (at the end ul>li) using a second custom component blog-post. I tried it without nesting and it worked fine. With the nesting of custom component I can expand and close only the first post.
Here the code. The template of blog.vue:
<template>
<v-content class="blog">
<v-container fluid>
<v-row>
<v-col xs3="xs3"></v-col>
<v-col xs6="xs6">
<h5>Blog</h5>
<div class="loading" v-if="loading">
Loading...
</div>
<div v-if="error" class="error">
{{ error }}
</div>
<div v-if="posts" class="content">
<v-collapsible>
<template v-for="post in posts" >
<blog-post :post="post"></blog-post>
</template>
</v-collapsible>
</div>
</v-col>
</v-row>
</v-container>
</v-content>
</template>
And the template of blog-post.vue:
<template>
<li class="blog-post">
<v-collapsible-header>{{ post.title }}</v-collapsible-header>
<v-collapsible-body>
<v-card>
<v-card-text class="grey lighten-3">{{ post.body }}</v-card-text>
</v-card>
</v-collapsible-body>
</li>
</template>
Heders and bodies of the accordeon are filled correctly.
instead of <template v-for try <li v-for, like following inside blog.vue:
<div v-if="posts" class="content">
<v-collapsible>
<li v-for="post in posts" >
<blog-post :post="post"></blog-post>
</li>
</v-collapsible>
</div>
and in template of blog-post.vue:
<template class="blog-post">
<v-collapsible-header>{{ post.title }}</v-collapsible-header>
<v-collapsible-body>
<v-card>
<v-card-text class="grey lighten-3">{{ post.body }}</v-card-text>
</v-card>
</v-collapsible-body>
</template>