erro while using bootstrap-vue in vue3 project - vue.js

I am working on bootstrap-vue but I cannot add the functionalities of bootstrap. the code of main.js is
import { createApp } from 'vue'
import App from './App.vue'
import "bootstrap/dist/css/bootstrap.css"
import"bootstrap-vue/dist/bootstrap-vue.css"
createApp(App).mount('#app')
and the code of Helloworld.vue file is
<template>
<div>
<h1>hello from helloworld</h1>
<h5>Pressed and un-pressed state</h5>
<b-button :pressed="true" variant="success">Always Pressed</b-button>
<b-button :pressed="false" variant="success">Not Pressed</b-button>
<h5 class="mt-3">Toggleable Button</h5>
<b-button :v-bind="myToggle" variant="primary">Toggle Me</b-button>
<p>Pressed State: <strong>{{ myToggle }}</strong></p>
<h5>In a button group</h5>
<b-button-group size="sm">
<b-button
v-for="(btn, idx) in buttons"
:key="idx"
:v-bind="btn.state"
variant="primary"
>
{{ btn.caption }}
</b-button>
</b-button-group>
<p>Pressed States: <strong>{{ btnStates }}</strong></p>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
myToggle: false,
buttons: [
{ caption: 'Toggle 1', state: true },
{ caption: 'Toggle 2', state: false },
{ caption: 'Toggle 3', state: true },
{ caption: 'Toggle 4', state: false }
]
}
},
computed: {
btnStates() {
return this.buttons.map(btn => btn.state)
}
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
what I do to implement the bootstrap-vue in this project

In your main.js file you are missing bootstrap-vue import. Try the below for vue3, it worked for me. Please note: create a const for app.
import { createApp } from 'vue'
import BootstrapVue3 from 'bootstrap-vue-3'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import App from './App.vue'
const app = createApp(App)
app.use(BootstrapVue3)
app.mount('#app')

Related

VueBankCard component is not displayed

I have tried to place component of bank card (avto-dev/bank-card-vue-component) in my frontend application on Vue.js, but I can't find this component in my frame after I followed their instructions on Github.
Here you can see my package.json file:
"dependencies": {
"#avto-dev/bank-card-vue-component": "^1.3.0",
...
...
},
main.js:
import VueBankCard from "#avto-dev/bank-card-vue-component"
import "#avto-dev/bank-card-vue-component/dist/bank-card-vue-component.css"
const app = createApp(App)
app.use(PrimeVue).use(router)
...
...
app.component('VueBankCard', VueBankCard)
and Profile.vue where I use this component:
<template>
<div class="profile">
<div class="bank-card-block">
<Card class="custom-card bank-card">
<template>
<VueBankCard
is-small
is-new
></VueBankCard>
</template>
</Card>
</div>
</div>
</template>
<script>
export default {
name: "Profile",
data(){
return{
valueFields: {
cardName: "",
cardNumber: "",
cardMonth: "",
cardYear: "",
cardCvv: "",
},
}
}
}
</script>
<style scoped>
.profile{
display: flex;
width: 94%;
}
.bank-card-block{
width: 45%;
}
.bank-card{
border-radius: 15px;
}
</style>
I have no hypothesis where it can be mistake.
Can you explain me what I have skipped, because all what I have done was only according to instructions in the github of this component.

How to pass <slots> content (provided by router-view) data back to component where slot is declared

I have 3 components: App.vue (Entry point), slotWrapper.vue (Wrapping component), About.vue (Page Content).
Inside the 'App.vue' i have the router-view setup which is wrapped with 'slotWrapper.vue' component. The 'slotWrapper' component has a <slot> where the current route will be rendered.
My question: Inside the About.vue page (which will be rendered instead of the <slot>, of the slotWrapper.vue component) I have a computed value which I somehow need to pass back to 'slotWrapper.vue' component to use. How would I achieve such a thing.
I looked into ScopedSlots but I can't figure our how to use it where the content rendered is provided by a router.
Link to: CodeSanbox
App.Vue
<template>
<div id="app">
<slotWrapper>
<router-view />
</slotWrapper>
</div>
</template>
<script>
import slotWrapper from "./components/SlotWrapper.vue";
export default {
name: "app",
components: {
slotWrapper,
},
};
</script>
SlotWrapper.vue
<template>
<div class="wrpperClass">
<slot />
</div>
</template>
<script>
export default {
name: "SlotWrapper",
};
</script>
<style scoped>
.wrpperClass {
width: 50%;
height: 50%;
color: black;
background-color: lightblue;
}
</style>
About.vue
<template>
<div id="app">
<slotWrapper>
<router-view />
</slotWrapper>
</div>
</template>
<script>
import slotWrapper from "./components/SlotWrapper.vue";
export default {
name: "app",
components: {
slotWrapper,
},
};
</script>
<style>
#app {
margin: 60px;
}
.link {
display: inline-block;
padding: 10px;
}
.router-link-active {
color: green;
}
</style>
Router: index.js
import Vue from "vue";
import Router from "vue-router";
import About from "../components/About";
Vue.use(Router);
export default new Router({
mode: "history",
routes: [
{ path: "/", redirect: "about" },
{
path: "/about",
component: About
// props: (route) => ({ name: route.query.name })
}
]
});
For those who might face this issue. I figured that you can pass props to <router-view> and listen to emits. Since you can listen to emits I simply emit from the about.vue page and listen on the app.vue, and later using props I pass the variable down to slotWrapper.vue.
App.vue
<template>
<div id="app">
<slotWrapper :propToPass="propToPass">
<router-view #comp-data="receiveFunction" />
</slotWrapper>
</div>
</template>
<script>
import slotWrapper from "./components/SlotWrapper.vue";
export default {
name: "app",
data() {
return { propToPass: null };
},
components: {
slotWrapper,
},
methods: {
receiveFunction(data) {
this.propToPass = data;
console.log("From emit: ", data);
},
},
};
</script>
About.vue
<template>
<div>
<h3>About Page</h3>
<p>
I need this data:
<span style="color: green">'ComputedData'</span> available inside
'SlotWrapper'
</p>
<p>{{ ComputedData }}</p>
</div>
</template>
<script>
export default {
name: "About",
data() {
return {
someVariable: "'someVariable'",
};
},
mounted() {
setTimeout(this.sendData, 2000);
},
computed: {
ComputedData() {
return (
this.someVariable + " How do I become accessible inside slotWrapper?"
);
},
},
methods: {
sendData() {
this.$emit("comp-data", this.ComputedData);
},
},
};
</script>

Opening a modal from each row in table of Bootstrap-Vue

I'm using Vue2 and Bootstrap-Vue. I have a table with data (I use b-table). I want to have "edit" option on each row in order to edit the table. This option (which is an icon of gear) will open a modal and display a view boxes. In my view I have:
<template>
<div>
<b-table class="text-center" striped hover
:items="items"
:bordered=tableBordered
:fields=tableFields
:label-sort-asc=tableLabelSortAsc>
<template #cell(view)="data">
<a target="_blank" rel="noopener" class="no-link" :href="data.item.url">
<b-icon icon="eye-fill"/>
</a>
</template>
<template #cell(edit)="data">
<b-icon icon="gear-fill"/>
<edit-info-modal :data="data"/>
</template>
</b-table>
</div>
</template>
<script>
import EditInfoModal from './EditInfoModal.vue';
import { BIcon } from 'bootstrap-vue';
export default {
components: {
'b-icon': BIcon,
'edit-info-modal': EditInfoModal
},
data() {
return {
tableBordered: true,
tableLabelSortAsc: "",
tableFields: [
{ sortable: false, key: 'edit', label: 'edit' },
{ sortable: true, key: 'comments', label: 'comments' },
{ sortable: false, key: 'view', label: 'view' }
],
items: [
{
"comments": "test",
"url": "some_url"
}
]
}
}
}
</script>
<style scoped>
div {
margin: auto 0;
width: 100%;
}
a.no-link {
color: black;
text-decoration: none;
}
a:hover.no-link {
color: black;
text-decoration: none;
cursor: pointer;
}
</style>
It creates a table with three columns - the view column (with eye icon) which redirects to the url, the comments column and the edit column (with gear icon) which should open the modal.
Now, I'm trying to have the modal in a separated Vue file called EditInfoModal:
<template>
<div>
<b-modal id="modal-1" title="BootstrapVue">
<p class="my-4">Hello from modal!</p>
</b-modal>
</div>
</template>
<script>
import { BModal } from 'bootstrap-vue';
export default {
props: {
data: Object
},
components: {
'b-modal': BModal
}
}
</script>
<style scoped>
div {
margin: auto 0;
width: 100%;
}
</style>
First of all, it does not open the modal. Reading over the internet I noticed that I should add isModalOpen field and update it each time and then create the watch method. But here I have a modal for each row. What is the recommended way to keep track of the opened modal (only one is opened at any given time)?
Step 1: install BootstrapVue package and references in main.js
import { BootstrapVue, BootstrapVueIcons } from "bootstrap-vue";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";
Vue.use(BootstrapVue);
Vue.use(BootstrapVueIcons);
Step 2: App.vue component
<template>
<div id="app">
<b-table
class="text-center"
striped
hover
:items="items"
:bordered="tableBordered"
:fields="tableFields"
:label-sort-asc="tableLabelSortAsc">
<template #cell(view)="data">
<a target="_blank" rel="noopener" class="no-link" :href="data.item.url">
<b-icon icon="eye-fill" />
</a>
</template>
<template #cell(edit)="data">
<b-icon icon="gear-fill" #click.prevent="editTable(data)" />
</template>
</b-table>
<edit-info-modal :data="data" :showModal="showModal" />
</div>
</template>
<script>
import { BIcon, BTable } from "bootstrap-vue";
import EditInfoModal from "./components/EditInfoModal.vue";
export default {
name: "App",
components: {
"b-table": BTable,
"b-icon": BIcon,
"edit-info-modal": EditInfoModal,
},
data() {
return {
tableBordered: true,
tableLabelSortAsc: "",
tableFields: [
{ sortable: false, key: "edit", label: "edit" },
{ sortable: true, key: "comments", label: "comments" },
{ sortable: false, key: "view", label: "view" },
],
items: [
{
comments: "Vue CRUD Bootstrap app",
url: "https://jebasuthan.github.io/vue_crud_bootstrap/",
},
{
comments: "Google",
url: "https://www.google.com/",
},
],
data: "",
showModal: false,
};
},
methods: {
editTable(data) {
this.data = Object.assign({}, data.item);;
this.showModal = true;
// this.$root.$emit("edit-table", Object.assign({}, data));
// this.$bvModal.show("modal-1");
},
},
};
</script>
<style scoped>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
div {
margin: auto 0;
width: 100%;
}
a.no-link {
color: black;
text-decoration: none;
}
a:hover.no-link {
color: black;
text-decoration: none;
cursor: pointer;
}
</style>
Step 3: Child component EditInfoModal.vue
<template>
<div>
<b-modal v-model="showModal" id="modal-1" title="Edit Table">
<p class="my-4">Hello from modal!</p>
<p>Comments: {{ data.comments }}</p>
<p>
URL: <a :href="data.url">{{ data.url }}</a>
</p>
</b-modal>
</div>
</template>
<script>
import { BModal } from "bootstrap-vue";
export default {
// data() {
// return {
// data: "",
// showModal: "",
// };
// },
props: ["data", "showModal"],
components: {
"b-modal": BModal,
},
// mounted() {
// this.$root.$on("edit-table", (data) => {
// this.data = data.item;
// });
// },
};
</script>
<style scoped>
div {
margin: auto 0;
width: 100%;
}
</style>
DEMO Link

BootstrapVue - Bootstrap CSS is being added to my Vue app multiple times

I'm using BootstrapVue and have set it up as per the docs. What I'm seeing though is that for every component in my Vue app that uses a BootstrapVue component, I'm getting the Bootstrap embedded in my rendered HTML. In this case, I have 27 instances of the same stylesheet being added.
I can't see where the issue is.
Here's my main.js file
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { BRow, BCol, BContainer } from 'bootstrap-vue'
import {InlineSvgPlugin} from "vue-inline-svg/dist/vue-inline-svg";
import VueSvgIconPolyFill from "#yzfe/vue-svgicon-polyfill";
Vue.config.productionTip = false
Vue.use(VueSvgIconPolyFill);
Vue.use(BCol, BRow, BContainer)
Vue.use(require('vue-moment'))
Vue.use(InlineSvgPlugin)
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
And here's an example of a Vue component using BootstrapVue
<template>
<section class="latest-news">
<b-container>
<b-row class="latest-news__title-bar">
<b-col class="d-flex align-items-center" :sm="12" :md="10">
<h2>
{{blockTitle}}
<a
href="#"
title="Collapse this section"
:class="`collapse-control ` + (isCollapsed ? 'collapse-control--collapsed' : '')"
#click.prevent="isCollapsed = !isCollapsed"
v-html="(isCollapsed) ? 'Show' : 'Hide'"
></a>
</h2>
</b-col>
<b-col class="d-flex justify-space-around" v-if="showSearchBar">
<ContentSearchBar title="Search news"/>
</b-col>
<b-col class="d-flex justify-content-end">
<Toolbar controls="news" :display-sorter="false" v-if="!isCollapsed && news.length"/>
</b-col>
</b-row>
<b-row v-if="!isCollapsed">
<b-col
cols="12"
:sm="smCols"
:md="mdCols"
v-for="(item, index) in news"
:key="`news` + index"
:class="((index < numberNewsItems) || !numberNewsItems) ? `latest-news__col` : ``"
>
<NewsItem
v-if="(index < numberNewsItems) || numberNewsItems === null"
:show-excerpt="showExcerpt"
:news="item"
:item-index="index"
:format="newsListFormat"
/>
</b-col>
</b-row>
<b-row v-if="news && news.length === 0 && isSearch && !isCollapsed">
<b-col cols="12">There are no news item results for your search term "{{$route.params.query}}"</b-col>
</b-row>
</b-container>
</section>
</template>
<script>
import NewsItem from "./NewsItem";
import ContentSearchBar from "./ContentSearchBar";
import Toolbar from "./Toolbar";
import store from '../store';
import {mapGetters} from 'vuex';
import NewsService from '../services/NewsService'
export default {
name: "LatestNews",
store: store,
props: {
showExcerpt: {
default: true,
},
showSearchBar: {
default: false,
},
numberNewsItems: {
default: null
},
'isSearch': {
default: false
},
},
data() {
return {
news: [],
isCollapsed: false
}
},
mounted() {
if (this.isSearch) {
this.searchNews()
} else {
this.getNews()
}
},
methods: {
async getNews() {
const response = await NewsService.all()
this.news = response.data
},
async searchNews() {
let query = this.$route.params.query;
const response = await NewsService.search(query);
this.news = response.data.results
}
},
components: {Toolbar, ContentSearchBar, NewsItem},
computed: {
blockTitle() {
if (this.isSearch) {
return 'News search results for "' + this.$route.params.query + '"'
} else {
return 'Latest News'
}
},
...mapGetters([
'newsListFormat'
]),
smCols() {
if (this.newsListFormat === 'list') {
return '12'
} else {
return '6'
}
},
mdCols() {
if (this.newsListFormat === 'list') {
return '12'
} else {
return '3'
}
},
}
}
</script>
<style lang="scss">
.latest-news {
&__col {
margin-bottom: 24px;
}
&__title-bar {
margin-bottom: 20px;
h2 {
margin-bottom: 0;
}
}
}
</style>
This is how Chrome dev tools shows the HTML when yarn serveed
This has been resolved :)
The issue was caused by including the bootstrap scss files in an scss file that was #imported into Vue's main.js so that Bootstrap's mixins could be used on single file component's styles
Removing the Bootstrap scss imports and importing the bootstrap css files in the main.js file fixed the issue.

Add searchbar for vue2-leaflet

Hi do somebody know or have some samples of code how to add searchbar for vue2-leaflet map, I have tried the following https://www.npmjs.com/package/vue2-leaflet-geosearch but failed, do you know any alternatives how to resolve it,hope for your help, thanks . This is code that works and I would like to add searchbar in the code .
<template>
<div>
<b-modal size="md" :visible="visible" #hidden="$emit('clear')" #shown="modalShown" title="Event details">
<div class="foobar1">
<l-map :minZoom="3" :zoom="13" ref="mymap" #click="addMarker">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<!-- <l-marker :lat-lng="center"></l-marker> -->
</l-map>
</div>
<template slot="modal-footer">
<b-btn variant="danger" #click="">Delete</b-btn>
</template>
</b-modal>
</div>
</template>
<style scoped>
.foobar1 {
width: 450px;
height: 400px;
align: center;
}
</style>
<script>
import {LMap, LMarker, LTileLayer} from "vue2-leaflet";
import L from "leaflet"
export default {
name: "loc",
components: {
LMap,
LMarker,
LTileLayer,
L
},
data() {
return {
marker: L.latLng(77, 154.0),
visible: true,
url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}",
attribution:
'© OpenStreetMap contributors'
};
},
methods: {
plotCurrentLocation(map) {
var vm = this;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
var currLocation = new L.latLng(position.coords.latitude, position.coords.longitude);
if (vm.marker)
map.removeLayer(vm.marker);
vm.marker = L.marker([position.coords.latitude, position.coords.longitude], {}).addTo(map);
map.setView(currLocation, 11, {animation: true});
map.panTo(currLocation);
}, err => {
// alert(JSON.stringify(err))
}, {timeout: 30000, enableHighAccuracy: true, maximumAge: 75000})
} else {
alert("no");
}
},
async modalShown() {
var map = this.$refs.mymap.mapObject;
map.invalidateSize();
this.plotCurrentLocation(map);
},
addMarker(e) {
var map = this.$refs.mymap.mapObject;
// alert(JSON.stringify(this.marker.getLatLng()));
if (this.marker)
map.removeLayer(this.marker);
this.marker = L.marker([e.latlng.lat, e.latlng.lng], {}).addTo(map);
map.panTo(e.latlng);
}
}
}
</script>
Instructions on the npm package works fine. Something like this should work.
Remember to install and import the necessary libraries.
<template>
<div style="height: 300px; width: 100%" class="text-grey-10">
<l-map #click="addMarker" :zoom="zoom" :center="center">
<l-tile-layer :url="url" :attribution="attribution" />
<l-geosearch :options="geosearchOptions"/>
<l-marker v-if="locationMarker" :latlng="locationMarker"/>
</l-map>
</div>
</template>
<script>
import { LMap, LTileLayer, LMarker } from "vue2-leaflet";
import { OpenStreetMapProvider } from "leaflet-geosearch";
import LGeosearch from "vue2-leaflet-geosearch";
export default {
components: {
LMap,
LTileLayer,
LMarker,
LGeosearch
},
data: () => {
geosearchOptions: {
provider: new OpenStreetMapProvider()
}
}
}
</script>