Trying to hide and show icon using vue js - vue.js

I am trying to hide and show a font awesome 5 icon on click. The value changes behind the scene but the icon isn't being changed. I have tried the other class bindings that vue js has to offer but it produced the same result.
<template>
....
<a href="#" class="social-button" #click.prevent="showAttribute(index)" rel="tooltip" data-color-class="primary" data-animate="animated fadeIn" data-original-title="" data-toggle="tooltip" data-placement="bottom">
<i class="fa fa-eye" v-if="category.attributes[index].show"></i>
<i class="fa fa-eye-slash" v-else></i>
</a>
....
</template>
<script>
export default {
...
showAttribute(index){
this.category.attributes[index].show = !this.category.attributes[index].show;
},
...
}
</script>

try with this v-if="!category.attributes[index].show" instead fo v-else
<template>
....
<a href="#" class="social-button" #click.prevent="showAttribute(index)" rel="tooltip" data-color-class="primary" data-animate="animated fadeIn" data-original-title="" data-toggle="tooltip" data-placement="bottom">
<i class="fa fa-eye" v-if="category.attributes[index].show"></i>
<i class="fa fa-eye-slash" v-if="!category.attributes[index].show"></i>
</a>
....
</template>
<script>
export default {
...
showAttribute(index){
this.category.attributes[index].show = !this.category.attributes[index].show;
},
...
}
</script>
onPage load if you don't get the value or if you get the value null. then, you need to set the default value in the data()
here is the working example, https://codepen.io/anon/pen/rvqYgz

Related

Vue.js 2.6.12 with Bootstrap 5.1.0 - Issue with manual component initiation

Following up on my old thread Vue.js (2.x) with Bootstrap 5
I keep having issues when creating a bootstrap component wrapper in Vue.
The idea is to create a wrapper for each Bootstrap component that I want to use (not all of them).
The issue happened when I tried to create a bootstrap.Dropdown wrapper. The dropdown menu is shown properly when clicked, but it didn't auto-close when clicking outside (somewhere else).
<template>
<div ref="el" class="dropdown">
<button
class="btn btn-primary dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
Select...
</button>
<ul class="dropdown-menu">
<slot></slot>
</ul>
</div>
</template>
<script>
import { Dropdown } from 'bootstrap';
export default {
name: 'BootstrapDropdown',
data() {
return {
dropdown: null,
};
},
mounted() {
const { el } = this.$refs;
this.dropdown = new Dropdown(el, {
autoClose: true,
});
['show', 'shown', 'hide', 'hidden'].forEach((e) => {
el.addEventListener(`${e}.bs.dropdown`, () => {
this.$emit(e);
});
});
},
};
</script>
Any ideas are welcomed. Thanks in advance.
I think it's not working because the Dropdown instance needs to be set on the trigger element, not the container. Change the "el" ref to the trigger button...
<template>
<div class="dropdown">
<button
ref="el"
class="btn btn-primary dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
Select...
</button>
<ul class="dropdown-menu">
<slot></slot>
</ul>
</div>
</template>
Demo

Collapsing vertical menu in element.io

I try to create a layout with element.io which has a collapsing sidebar menu.
It works quite well, the only problem is that I do not gain anything since the width of the menu and the content part are fixed.
My code looks like this:
<template>
<el-row>
<el-col :span="4">
<template>
<el-menu :router="true"
:default-active="$route.path"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
:collapse="isCollapse"
class="el-menu-vertical-demo"
>
<template v-for="rule in routes">
<el-menu-item :index="rule.path">
<i :class="rule.icon"></i>
<span slot="title">{{ rule.name }}</span>
</el-menu-item>
</template>
</el-menu>
</template>
</el-col>
<el-col :span="20">
<el-row>
<el-radio-group v-model="isCollapse" style="margin-bottom: 20px;">
<el-radio-button :label="true" :disabled="isCollapse" border>
<i class="fas fa-caret-left"></i>
</el-radio-button>
<el-radio-button :label="false" :disabled="!isCollapse" border>
<i class="fas fa-caret-right"></i>
</el-radio-button>
</el-radio-group>
</el-row>
<el-row>
<router-view></router-view>
</el-row>
</el-col>
</el-row>
</template>
<script>
export default {
data() {
return {
routes: this.$router.options.routes,
activeLink: null,
isCollapse: false
};
},
mounted: function () {
},
methods: {
}
};
</script>
How can I fix it so the content block will occupy 100% of the available width?
Ok, I found a simple solution.
First, I moved to element-io elements. The menu is now embedded inside el-aside tag, while the main part is embedded inside an el-container tag.
Second, I added a dynamic css class to the el-aside tag:
<el-aside v-bind:class="[isCollapse ? 'menu-collapsed' : 'menu-expanded']">
Now, if you don't want to mess around with transitions, simply add to the el-menu component :collapse-transition="false" and that's it!

How to transfer data between components (siblings) Vue?

In the HeaderComponent method 'clickPrices' is called on click
<template>
<header>
<div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm">
<h5 class="my-0 mr-md-auto font-weight-normal">Company name</h5>
<nav class="my-2 my-md-0 mr-md-3">
<a class="p-2 text-dark" href="#">Features</a>
<a class="p-2 text-dark">Enterprise</a>
<a class="p-2 text-dark" #click="clickPrices()">Get pricing</a>
</nav>
<a class="btn btn-outline-primary " href="#">Sign up</a>
</div>
</header>
</template>
<script>
export default {
name: "HeaderComponent",
methods: {
clickPrices() {
...
},
},
}
</script>
<style scoped>
</style>
and there is a Pricing Component in which I make a request to the server in the method 'getPricing'
<template>
<div class="wrap-pricing">
<div class="pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
<h1 class="display-4">Pricing</h1>
<p class="lead">Quickly build an effective pricing table for your potential customers with this Bootstrap example. It’s built with default Bootstrap components and utilities with little customization.</p>
</div>
<div class="container">
<div class="card-deck mb-3 text-center">
<div class="card mb-4 shadow-sm">
<div class="card-header">
<h4 class="my-0 font-weight-normal">Lorem</h4>
</div>
<div class="card-body">
<h1 class="card-title pricing-card-title">$10 <small class="text-muted">/ mo</small></h1>
<ul class="list-unstyled mt-3 mb-4">
<li>Lorem</li>
<li>Lorem</li>
<li>Lorem</li>
<li>Lorem</li>
</ul>
<button type="button" class="btn btn-lg btn-block"></button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import router from '../routes.js';
import { axios } from 'axios';
export default {
name: "PriceComponent",
methods: {
getPricing() {
axios.get('api/pricing').then((response) => {
//some actions
router.push('prices');
});
},
},
}
</script>
<style scoped>
</style>
How should I process the result of the 'сlickPrices' HeaderComponent method?
Or am I waiting for your ways, how can I get data in another by clicking in one component
You can emit an event and let the parent component handle the fetching and pass the data as props to the child component.
Or another way is to directly listen to the event as follows
Component 1:
this.$root.$emit('clickPrices', data);
Component 2:
mounted() {
this.$root.$on('clickPrices', data => {
this.getPricing();
});
}
Check out the answer by #alex
Since you are using 2 independent components (one is not included in the other), you cannot pass props
Things you can do -
Instead of fetching all the prices on click, just create a created hook like so, which will fetch all the pricing details whenever your component is created -
created () {
this.getPricing()
},
methods: {
getPricing() {
axios.get('api/pricing').then((response) => {
//some actions
router.push('prices');
});
},
},
Use State and when a user clicks on the button, pricing details are fetched and added in the state. And you can just use the state anywhere in your application like so -
this.$store.state.prices
Let me know if it works, if not we will find some other solution for you!

Show Div When Hover Based on ID in Vue JS

I have a div that when i want hover to it, it will show other div. However, my first div is dynamic, it has an ID. So how will i able to hover to ID based on its ID?
It should be #mouseenter="hoverService{{services.id}} = true" but it causes error. So i made the code below to just static.
Here's my code below:
<template>
<div
class="col-md-3"
v-for="(services, index) in servicesFiltered"
:key="index"
#mouseenter="hoverService = true"
#mouseleave="hoverService = false"
>
<div class="service_background" v-if="hoverService">
<div class="mb-1" v-for="(sub_services, index) in services.menu_items" :key="index">
<router-link
:to="{ path: `/${sub_services.data}`}"
>
<a
href="#"
class="btn btn-outline-primary w-100 services_button"
>{{sub_services.text }}</a>
</router-link>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
hoverService: false
};
}
};
</script>
Try this code
https://codesandbox.io/s/y7p9qyyovz
You need to maintain hover for each item you can not manipulate using single variable for multiple items.

Is possible to pass data from slot-component to parent in vueJS?

I'm new in VueJS and I'm try to do something like this
I have 3 components, siderbar ; siderbar-item and sidebar-drop
siderbar.vue is a wrapper when you can put siderbar-item and sidebar-drop, and inside sidebar-drop you can put sidebar-item too
for example:
<sidebar>
<sidebar-item url="myurl" title="Dashboard" icon="fas fa-tachometer-alt" badge=""></sidebar-item>
<sidebar-drop title="News" icon="fas fa-tachometer-alt">
<sidebar-item url="myurl_news" title="News list" icon="fas fa-tachometer-alt" badge=""></sidebar-item>
<sidebar-item url="myurl_news_add" title="Add News" icon="fas fa-tachometer-alt" badge=""></sidebar-item>
</sidebar-drop>
<sidebar-drop title="Categories" icon="fas fa-tachometer-alt">
<sidebar-item url="myurl_categories" title="Categories List" icon="fas fa-tachometer-alt" badge=""></sidebar-item>
</sidebar-drop>
</sidebar>
sidebar.vue is very simple:
<aside>
<slot></slot>
</aside>
sidebar-item.vue
<template>
<ul class="menu-list" >
<li>
<a :href="url" :class="{'is-active': is_active }">
<span class="icon"><i v-if="icon" :class="icon"></i></span>
{{ title }}
<span v-if="badge" class="button badge is-info is-small is-pulled-right "> {{ badge }}</span>
</a>
</li>
</ul>
</template>
<script>
export default {
props: ['title', 'url', 'icon', 'badge'],
data() {
return {
is_active: this.$current_url === this.url
}
}
}
</script>
and sidebar-drop.vue
<template>
<ul class="menu-list" v-if="title">
<li #click="openMenu" :class="{'is-open': is_open}">
<a class="">
<span v-if="icon" class="icon"><i class="fas fa-tachometer-alt"></i></span>
{{ title }}
<span class="badge is-pulled-right" style=""> <i class="fas fa-chevron-left"></i> </span>
</a>
<slot></slot>
</li>
</ul>
</template>
<script>
export default {
props: ['title', 'icon'],
data() {
return {
is_open: false,
}
},
methods: {
openMenu(){
this.is_open = !this.is_open;
},
}
}
</script>
It works great, but I have a little problem. If you notice, sidebar-item has a data called "is_active", it only put a CSS class that this item is active. Great.
Now I'm trying to get into sidebar-drop if a least one of his children has data "is-active" in true, change the is_open sidebar-drop parent data to true.
Example: I click "News" item.
Ul li News is active... works!
Ul li parent drop is open... don't work
Is possible make that?
Thanks everyone!
Update:
I put it in Fiddler to more clear:
https://jsfiddle.net/h35qy2zs/
I do in sidebar-item a random is_active.
If any child of sidebar-drop (sidebar-item's) data is_active:true, sidebar-drop data is_open is true too.
So, it show in color yellow and open
Result:
But now, both are closed at refresh page.