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>
Related
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>
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.
i am new in vue.js and get some problem while displaying data in b-table. my data from database is fetched properly. and i passed from one file to products.vue and received data in products.vue as props. when i console my data is showing in console properly, but when i used to display data in b-table, i got some problem. data is not displaying correctly.
please let me know where is mistake in my code?
Products.vue (script tag)
<script>
export default {
props: ['category','singular', 'plural','products'],
data() {
return {
title: `All ${this.plural}`,
items: [],
editing: false,
weight_assignment: false,
model: null,
formTitle: '',
fields: [
{
key: 'index',
label: 'S.No.'
},
{
key: 'name',
sortable: true
},
{
key: 'weights'
},
{
key: 'default_weight',
sortable: true
},
{
key: 'status',
sortable: true
},
{
key: 'action'
}
],
}
</script>
Product.vue (template tag)
<template>
<div class="row">
</div>
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">{{title}}</h3>
<div class="card-tools">
<b-button variant="primary" #click="newItem">New {{singular}}</b-button>
<div></div>
</div>
</div>
<div class="card-body table-responsive p-0">
<spinner v-if="$root.loading"></spinner>
<b-table ref="table" v-for="type in this.products" :items="type" :key="type.id" :fields="fields" bordered hover :head-variant="'light'" responsive="sm" v-else>
<template v-slot:cell(index)="type">
{{ type.index + 1 }}
</template>
<template v-slot:cell(name)="type">
<b-img thumbnail fluid :src="getImageUrl(type.image)" alt="Image 1" class="thumb-img"></b-img>
{{type.name}}
</template>
<template v-slot:cell(weights)="type">
<span v-weights="type.item"></span>
</template>
<template v-slot:cell(default_weight)="type">
<span v-floatFormatter="type.default_weight"></span>{{type.unit.sname}}
</template>
<template v-slot:cell(status)="type">
<span v-if="type.status" class="text-success text-bold">Active</span>
<span class="text-danger" v-else>Inactive</span>
</template>
<template v-slot:cell(action)="data">
<a #click.prevent="editItem(data.index)"><i class="fa fa-edit" aria-hidden="true" title="Update product" v-b-tooltip.hover></i></a>
<a #click.prevent="assignWeights(data.index)"><i class="fa fa-balance-scale" title="Assign weights" aria-hidden="true" v-b-tooltip.hover></i></a>
</template>
</b-table>
</div>
</div>
</div>
</div>
</template>
v-for="type in this.products" - try to delete this key. In template tag do not use this keyword to access data or any other values.
I have spotted you pass data completely wrong way. Please use below variant and tell me if it work.
EDITED template:
<template>
<div class="row">
</div>
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">{{title}}</h3>
<div class="card-tools">
<b-button variant="primary" #click="newItem">New {{singular}}</b-button>
<div></div>
</div>
</div>
<div class="card-body table-responsive p-0">
<spinner v-if="$root.loading"></spinner>
<b-table ref="table" :items="products" :fields="fields" bordered hover :head-variant="'light'" responsive="sm" v-else>
<template v-slot:cell(index)="data">
{{ data.index + 1 }}
</template>
<template v-slot:cell(name)="data">
<b-img thumbnail fluid :src="getImageUrl(data.image)" alt="Image 1" class="thumb-img"></b-img>
{{data.name}}
</template>
<template v-slot:cell(weights)="data">
<span v-weights="data.item"></span>
</template>
<template v-slot:cell(default_weight)="data">
<span v-floatFormatter="data.default_weight"></span>{{data.unit.sname}}
</template>
<template v-slot:cell(status)="data">
<span v-if="data.status" class="text-success text-bold">Active</span>
<span class="text-danger" v-else>Inactive</span>
</template>
<template v-slot:cell(action)="data">
<a #click.prevent="editItem(data.index)"><i class="fa fa-edit" aria-hidden="true" title="Update product" v-b-tooltip.hover></i></a>
<a #click.prevent="assignWeights(data.index)"><i class="fa fa-balance-scale" title="Assign weights" aria-hidden="true" v-b-tooltip.hover></i></a>
</template>
</b-table>
</div>
</div>
</div>
</template>
I tried a lot, after all this, my code is working correctly now, this given below code is the right solution.
<b-table ref="table" :items="products" :fields="fields" bordered hover :head-variant="'light'" responsive="sm" v-else>
<template v-slot:cell(index)="data">
{{ data.index+1 }}
</template>
<template v-slot:cell(name)="data">
<b-img thumbnail fluid :src="getImageUrl(data.item.image)" alt="Image 1" class="thumb-img"></b-img>
{{data.item.name}}
</template>
<template v-slot:cell(weights)="data">
<span v-weights="data.item"></span>
</template>
<template v-slot:cell(default_weight)="data">
<span v-floatFormatter="data.item.default_weight"></span>{{data.item.unit.sname}}
</template>
<template v-slot:cell(status)="data">
<span v-if="data.status" class="text-success text-bold">Active</span>
<span class="text-danger" v-else>Inactive</span>
</template>
<template v-slot:cell(action)="data">
<a #click.prevent="editItem(data.item.id)"><i class="fa fa-edit" aria-hidden="true" title="Update product" v-b-tooltip.hover></i></a>
<a #click.prevent="assignWeights(data.item.id)"><i class="fa fa-balance-scale" title="Assign weights" aria-hidden="true" v-b-tooltip.hover></i></a>
</template>
</b-table>
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>
I am new to vue and really struggle to get my dynamically created accordion to expand when clicked on.
I think its something basic I am missing but I have been stuck for a while.
This codepen show my troubles, I cant figure it out?
<template>
<div role="tablist">
<b-card v-for="(item, index) in feature_info" no-body class="mb-1">
<b-card-header header-tag="header" class="p-1" role="tab">
<b-button block href="#" v-bind:v-b-toggle="'accordion-' + index" variant="info">[[ item.layerName ]]</b-button>
</b-card-header>
<b-collapse v-bind:id="'accordion-' + index" accordion="my-accordion" role="tabpanel">
<b-card-body>
<b-card-text>Mock text</b-card-text>
</b-card-body>
</b-collapse>
</b-card>
</div>
</template>
Link to codepen
Your problem is the v-bind:v-b-toggle="'accordion-' + index".
v-b-toggle is a directive and you therefor don't need to use v-bind on it. So if you just remove v-bind: from it, it should work.
new Vue({
el: '#app',
delimiters: ['[[',']]'],
data: {
message:"Hello",
feature_info:[
{layerName: 'Hello Vue!'},
{layerName: 'Second'}
],
}
})
<link href="https://unpkg.com/bootstrap#4.4.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/bootstrap-vue#2.5.0/dist/bootstrap-vue.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.5.0/dist/bootstrap-vue.js"></script>
<div id="app">
<div role="tablist">
<b-card v-for="(item, index) in feature_info" no-body class="mb-1">
<b-card-header header-tag="header" class="p-1" role="tab">
<b-button block href="#" v-b-toggle="'accordion-' + index" variant="info">[[ item.layerName ]]</b-button>
</b-card-header>
<b-collapse v-bind:id="'accordion-' + index" accordion="my-accordion" role="tabpanel">
<b-card-body>
<b-card-text>Mock text</b-card-text>
</b-card-body>
</b-collapse>
</b-card>
</div>
</div>