Does vuejs project can import bootstrap.min.js file? - vue.js

I have a project in vuejs which bootstrap is already installed. I am using html, css project and converting into vuejs which bootstrap classes are used. However, dropdown bootstrap classes are not working for example, the below classes are not adding Show class when its getting clicked and normal html file is showing show class.
dropdown-toggle
dropdown-menu
I have
"bootstrap": "^5.1.3",
"bootstrap-vue": "^2.22.0",
"#popperjs/core": "^2.11.5",
Can someone please suggest something?
Thanks

Use show or shown
The in Bootstrap-Vue doesn't have a click event, but it does emit a show event shortly before the dropdown appears, including when it's clicked.
It immediately follows.
<b-nav-item-dropdown #show="doSomething">
Your code:
<b-nav-item-dropdown text="nav_title" #show="doSomething">
<b-dropdown-item href="#">
a
</b-dropdown-item>
<b-dropdown-item href="#">
a
</b-dropdown-item>
</b-nav-item-dropdown>
methods: {
doSomething() {
console.log('shown');
}
}
(You didn't find information for it on Vue's site because they didn't make the library.)

Related

Precompile VueJS template only files

I am writing a single page app with VueJS. I have a lot of html elements sharing the same style across differents files. To simplify my job and clear the template section I've created .vue files to encapsulate commom html block.
For example I have files like AccentBox.vue:
<template>
<div class="bg-accent rounded-lg p-4 flex cursor-pointer">
<div class="m-auto flex flex-row">
<slot></slot>
</div>
</div>
</template>
The problem is that it increase the bundle size a lot and in the browser side it has a big performance overhead.
Example of the Home.vue:
<Box class="mt-5">
<GrowingAnimation>
<Header1>Titre:</Header1>
<Text class="mt-2">{{todo.title}}</Text>
<ClickScale>
<AccentBox class="mt-5 flex flex-row gap-4">
<TrashIcon class="h-10" />
</AccentBox>
</ClickScale>
</Animation>
</Box>
I want to know if there is a way to "precompile / transform" those component so that in the browser vuejs does not have to render the AccentBox.vue component and avoid having huge trees of nested vuejs components.
I already use the vuejs build command but browser side AccentBox.vue still is a component and take time to be processed by vue.
Transforming this:
<Header1>Titre:</Header1>
into
<h1 class="text-3xl font-bold">Titre:</h1>
Is there any way to do it? Thanks in advance.
Because your AccentBox.vue file represents a full-blown component, it does contain more overhead than simply writing out some divs. However, in Vue 3, this overhead is rather minimal, and there isn't a way to precompile something like a macro.
Vue allows us to write stateless components that simply render HTML, using something called a render function. We can rewrite your AccentBox component like this:
import { h } from 'vue'
const AccentBox = (props, context) => {
return h(
'div',
{ class: 'bg-accent rounded-lg p-4 flex cursor-pointer' },
h(
'div',
{ class: 'm-auto flex flex-row' },
context.slots
)
)
}
export default AccentBox
We can then import it in exactly the same way as a standard Vue file:
import AccentBox from 'AccentBox.js'

<router-link> Vue Router #click event

I tried using a click event on a <router-link>. It works, but it is reloading the page everytime the link is clicked. I would like to avoid it but I can't figure out how.
I am aware that <router-link> does not accept a simple #click event. I saw on some forums that #click.I native would work, but as we know, that is deprecated.
So I would like to know if there is any solution other than wrapping the router link in a div and putting the listener on that div.
The reason why I want to do this is that I want to bind a class dinamicaly when the link is clicked. I have created a dropdown menu which is triggered onClick. But then when I follow a link inside that dropdown menu, the menu remains open. Therefore, I would like to have an additional #click event to dinamically bind a class (display: none) to the dropdown menu. The thing is that the items inside the dropdown are iterated which send parameters to a Vuex Mutation and therefore i can’t use regular tags and wrapping the router-links with a span or div is also not giving me the desired effect.
Thank you !
Regards,
T.
I have managed to solve the problem using a div wrapper and changing my css (that was preventing the code to work properly)
<div class="dropdown">
<a class="dropbtn" #click="dropClick"><i class="ri ico ri-draft-line"></i> Docs <i class="ri ico ri-arrow-drop-down-line ri-1x"></i></a>
<div class="dropdown-content" :class="{ 'dropdown-content-display': clicked }">
<div class="wrapper" v-for="route in $store.state.menuItems" :key="route.name" #click="dropClick">
<router-link :to="{ name: 'docs', params: { title: route.name } }"> <i :class="'ico ri ' + route.icon"></i> {{ route.name }}
</router-link>
</div>
</div>
</div>
If a understand your question, there is a "active-class" property on vue-router(router-link). You can set your classes dynamically by based on an active route.

Conditional wrapper rendering in vue

I'm making a link/button component which either can have a button or an anchor wrapper, a text and an optional icon. My template code below is currently rendering either an anchor or a button (with the exact same content) based on an if statement on the wrapper element, resulting in duplicate code.
<template>
<a v-if="link" v-bind:href="url" class="btn" :class="modifier" :id="id" role="button" :disabled="disabled">
{{buttonText}}
<svg class="icon" v-if="icon" :class="iconModifier">
<use v-bind="{ 'xlink:href':'#sprite-' + icon }"></use>
</svg>
</a>
<button v-else type="button" class="btn" :class="modifier" :id="id" :disabled="disabled">
{{buttonText}}
<svg class="icon" v-if="icon" :class="iconModifier">
<use v-bind="{ 'xlink:href':'#sprite-' + icon }"></use>
</svg>
</button>
</template>
Is there a more clean way for wrapping my buttonText and icon inside either an anchor or button?
I've solved my issue by intensive Google-ing! Found this issue regarding Vue on Github which pointed me in the right direction.
Small piece of backstory
I'm using Vue in combination with Storybook to build a component library in which a button can either be a button or an anchor. All buttons look alike (apart from color) and can be used for submitting or linking. To keep my folder structure ordered, I would like a solution that generates a multiple buttons types (with or without link) from one single file.
Solution
Using computed properties I'm able to "calculate" the necessary tag, based on the url property of my component. When a url is passed, I know that my button has to link to another page. If there is no url property it should submit something or preform a custom click handler (not in the sample code below).
I've created the returnComponentTag computed property to avoid placing any complex or bulky logic (like my original solution) in my template. This returns either an a or a button tag based on the existence of the url property.
Next, as suggested by ajobi, using the :is attribute I'm able to define the component tag based on the result of my computed property. Below a stripped sample of my final (and working) solution:
<template>
<component :is="returnComponentTag" v-bind:href="url ? url : ''" class="btn" :class="modifier" :id="id">
{{buttonText}}
</component>
</template>
<script>
export default {
name: "Button",
props: {
id: {
type: Number
},
buttonText: {
type: String,
required: true,
default: "Button"
},
modifier: {
type: String,
default: "btn-cta-01"
},
url: {
type: String,
default: ""
}
},
computed: {
returnComponentTag() {
return this.url ? "a" : "button"
}
}
};
</script>
You could extract the wrapping element into a dedicated component.
<template>
<a v-if="link" v-bind:href="url" class="btn" :class="modifier" :id="id" role="button" :disabled="disabled">
<slot></slot>
</a>
<button v-else type="button" class="btn" :class="modifier" :id="id" :disabled="disabled">
<slot></slot>
</button>
</template>
// You would use it like this
<SomeComponent /* your props here */ >
{{buttonText}}
<svg class="icon" v-if="icon" :class="iconModifier">
<use v-bind="{ 'xlink:href':'#sprite-' + icon }"></use>
</svg>
</SomeComponent>
There are multiple ways of doing this. Two examples would be the following based on the point of view:
You are defining two different components (Button or Anchor) and want to use a wrapper to render either one of them.
You could seperate the Wrapper Content into two components so that the wrapper only decides on which of the components to render (either the Button or the Anchor).
The problem with this approach could be you will have doubled code for methods and styling for the button and anchor component.
You are defining the content as a component and use the wrapper to define what to wrap the content in.
See Answer of https://stackoverflow.com/a/60052780/11930769
It would be great to know, why you would want to achive this. Maybe there are better solutions for your usecase. Cheers!

How to tell if an html tag in vue is a custom tag or not?

I'm new to Vue and I'm looking at an existing code that makes me question, where do the tags <u-col> and <u-row> come from?
My very little understanding of Vue so far is that you can create custom components and then use those components like html tags in the template. But my understanding is that if the component is to be used then it must be exported from where it is created and then imported at where it is being used.
Below is a part of the code that I'm not sure if <u-col> or <u-row> are custom made tags or if they're simply default vue tags? I don't think they're custom tags because I don't see any imports and I haven't found anything in the source code that tells me they are custom tags. But I don't think they are default vue tags either because I haven't seen them from my google searches. The closest I've come to is the <b-col> tag but I know that is from bootstrap.
<template>
<u-row class="mb-4 flex-nowrap">
<u-col class="text-sm text-700 text-right col-2 mr-4">
<span v-if="required" class="text-warning">*</span>{{label}}
</u-col>
<u-col>
<slot />
</u-col>
</u-row>
</template>
<script>
export default {
props: {
label: {
type: String
}
}
</script>
<style>
</style>
Any help is appreciated.

Vuejs not prompting bootstrap popover

I am using bootstrap popover with vuejs.
How can I trigger vue functionality?
In below code when I am clicking on add break link, it opens bootstrap popover, with click me button. Now here vuejs doesn't work, if I click on click me, it is not prompting alert.
<a data-toggle="popover" data-placement="top" v-d2d-popover data-content='<button v-on:click="alert(6)">click me</button>' href="javascript:void(0)" class="btn btn-link popover-notitle">
<i class="ace-icon fa fa-plus-circle bigger-120 green"></i>add break
</a>
Can anybody help me?
Since the button is just written in a string, it isn't being compiled by Vue. Here are a couple of ideas to try:
Use Vue for popover as well: https://yuche.github.io/vue-strap/#popover
Create popover content in a separate div (in your component so Vue will compile it) and then fetch the content for the popover:
{
content: $('#myPopoverContent').html(),
html: true
}