I have a Banner component. I want to change the image in there when i am navigating to different routes. Its like using different banner images for separate inner pages. I want to use that banner component as a nested component in other components.
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav m-auto custom-nav">
<li class="nav-item">
<router-link to="/">home</router-link>
</li>
<li class="nav-item">
<router-link to="/about-Us">about us</router-link>
</li>
<li class="nav-item">
<router-link to="/characters">characters</router-link>
</li>
<li class="nav-item">
<router-link to="/our-comics">comics</router-link>
</li>
</ul>
</div>
Banner component
<template>
<section class="banner-outer">
<img src="../assets/banner.jpg" alt class="img-fluid" />
<div class="banner-content-outer">
<div class="container">
<div class="banner-content-inner">
<h1>EXPLORE THE UNIVERSE</h1>
<h5>Dive into the dazzling domain of all the classic characters you love ...</h5>
</div>
</div>
</div>
</section>
</template>
About Us Component, Contact us Component
<template>
<banner />
</template>
In each page component, pass the image in as a prop to the banner component...
<template>
<banner which-banner="//path/to/img.png"></banner>
<div>component page content...</div>
</template>
In the banner Component...
<script>
...
{
props: ['whichBanner']
}
..
</script>
<template>
<section class="banner-outer">
<img :src="whichBanner" alt class="img-fluid" />
<div class="banner-content-outer">
<div class="container">
<div class="banner-content-inner">
...
</div>
</div>
</div>
</section>
</template>
Vue Codeply
you can use beforeEach :
router.beforeEach((to, from, next) => {
// check current route to set the valid image
// in vuex or localstorage or even a global window variable
if(to === 'about-us') {
// using global variable
window.bannerImagePath = 'path/to/about-us/banner.png';
// localstorage
localStorage.setItem('bannerImagePath', 'path/to/about-us/banner.png');
} else if( ... ) { ... }
return next();
});
Then you can get it in BannerComponent inside mounted() or set a method for that
Example :
<img :src="getCurrentBannerImage()" alt class="img-fluid" />
methods: {
getCurrentBannerImage() {
// global variable example
return require(window.bannerImagePath) // or any storage you choose
// localStorage
let _item = localStorage.getItem('bannerImagePath');
return require(_item) // or any storage you choose
}
},
Related
I have a problem in VueJS. I coding a website and i want to add a sun icon. I want to change theme when click icon. You knows; if theme is dark do light and the exact opposite. I think emit() is not work. But I am not sure.
This is codes:
Navbar.vue
<script setup>
import { RouterLink, RouterView } from 'vue-router'
defineEmits(['toggle'])
</script>
<template>
<div>
<nav class="navbar navbar-expand-lg" id="navbar">
<div class="container-fluid">
<a href="/" class="navbar-brand">
<span>osman<span>beyhan</span></span>
</a>
<div class="iconsTwo">
<i class="bi bi-sun-fill d-block d-lg-none" id="icon" #click="this.$emit('toggle')"></i>
<i class="bi bi-list navbar-toggler" data-bs-toggle="offcanvas" href="#offcanvasMenu" aria-controls="offcanvasMenu"></i>
</div>
<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasMenu" aria-labelledby="offcanvasMenuLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasMenuLabel">
<a href="/">
<span>osman<span>beyhan</span></span>
</a>
</h5>
<i class="bi bi-x-lg btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></i>
</div>
<div class="offcanvas-body">
<ul class="navbar-nav">
<li class="nav-item">
<a class="" href="/about">About Me</a>
</li>
<li class="nav-item">
<a class="" href="/projects">Projects</a>
</li>
<li class="nav-item">
<a class="" href="/contact">Contact</a>
</li>
</ul>
<hr id="line">
<ul class="nav-item d-flex d-md-flex" id="icons">
<li>
<a class="" target="_blank" href="https://www.instagram.com/osmn_byhn/?hl=tr">
<i class="fa-brands fa-instagram"></i>
</a>
</li>
<li>
<a class="" target="_blank" href="https://github.com/osmn-byhn">
<i class="fa-brands fa-github"></i>
</a>
</li>
<li>
<a class="" target="_blank" href=" https://wa.me/905350217844">
<i class="fa-brands fa-whatsapp"></i>
</a>
</li>
<li>
<a class="" target="_blank" href="https://www.linkedin.com/in/osman-beyhan-12304b23a/">
<i class="fa-brands fa-linkedin"></i>
</a>
</li>
<br>
<li id="ayrac" class="d-none d-lg-block"> | </li>
<li>
<i class="bi bi-sun-fill d-none d-lg-block mysun" id="icon"></i>
</li>
</ul>
</div>
</div>
</div>
</nav>
</div>
</template>
<style lang="scss" scoped>
#import '/public/Navbar.scss';
#import '/public/Theme.scss';
</style>
App.vue
<script setup>
import { RouterLink, RouterView } from 'vue-router'
import Navbar from './components/Navbar.vue'
import { ref } from 'vue'
var mode = ref('dark')
function toggle() {
if (mode === "dark") {
mode = "light"
console.log(mode)
} else {
mode = "dark"
console.log(mode)
}
}
</script>
<template>
<div class="app" :class="mode">
<Navbar :mode="mode" #toggle="toggle" />
<RouterView />
</div>
</template>
<style scoped lang="scss">
#import '../public/App.scss';
#import '../public/Theme.scss';
</style>
When i click sun icon; function is works but theme don't change:
enter image description here
Please help me!
In the script setup syntax, you shouldn't use $this when emitting something, instead you should handle it like this:
<script setup>
// more logic ...
const emit = defineEmits(["toggle"]);
</script>
<template>
<div>
<button #click="emit('toggle', someData)">toggle theme</button>
</div>
</template>
Then in the parent component:
<script setup>
const handleData = (param) => {
console.log("data passed was ", param);
}
</script>
<template>
<MyComponent #toggle="handleData()">
...
</MyComponent>
</template>
But also, you could just add the dark class to the body, and while it's outside the vue app instance, you could just handle the logic directly in the Navbar component and adding the class in vanilla javascript:
<!-- Navbar component, without emit -->
<script setup>
const toggle = () => {
if(document.body.classList.contains("dark")){
document.body.classList.remove("dark");
}else{
document.body.classList.add("dark");
}
}
</script>
When I click nav link on navbar it does not collapse.
Vue version 2.6.10.
<template>
<div class="nav-wrapper">
<nav>
<ul>
<li v-for="(route, index) in routings" :key="index">
<router-link :to="route.url">{{route.name}}</router-link>
</li>
<li>
Blog
</li>
<li class="visible-xs">
<Button v-if="!isLoggedIn" :label="loginButtonLabel" :isFilled="true" :action="goToLogin"/>
<UserWidget v-else :email="setFirstName" :title="'administrator'" :isUserMenu="true" :action="gotoDashboard"/>
</li>
</ul>
</nav>
</div>
</template>
This is the navbar what i talk about
This is the header part of the code. When click on the hamburger icon class 'mobile-menu-wrapper visible-xs' this will change to 'mobile-menu-wrapper visible-xs expanded'. There for I think it will be change to previous class its solve the matter. Please advise me to find the issue.
<template>
<div class="header-wrapper">
<div class="header-container container">
<Logo/>
<Nav class="hidden-xs" :routings="routings"/>
<Button v-if="!isLoggedIn" class="hidden-xs" :label="isLoggedIn ? 'Console' : 'Login / Sign-up'" :isFilled="true" :action="goToLogin"/>
<UserWidget class="hidden-xs" v-if="isLoggedIn" :email="setFirstName" :title="'administrator'" :isUserMenu="true" :action="gotoDashboard"/>
<div class="mobile-menu-icon-wrapper visible-xs" #click="getMobileMenu">
<i v-if="isMenuExpanded" class="mobile-menu-icon close-icon"></i>
<i v-if="!isMenuExpanded" class="mobile-menu-icon expand-icons"></i>
</div>
<div class="mobile-menu-wrapper visible-xs" :class="{'expanded': isMenuExpanded}">
<div class="menu-overlay" #click="getMobileMenu"></div>
<Nav :routings="routings" :eventBus="eventBus" :adminDetails="adminDetails" :isLoggedIn="isLoggedIn"/>
<div class="mobile-menu-icon-wrapper" #click="getMobileMenu">
<i v-if="isMenuExpanded" class="mobile-menu-icon close-icon"></i>
</div>
</div>
</div>
</div>
</template>
Try to add an onclick event in your router link to close the navigation bar, I don't see the code that you're using to open/close the nav, but you can emit an event like this:
Let's listen for the event closeNav in the parent component, by adding #closeNav in the Nav component:
<template>
<div class="header-wrapper">
<div class="header-container container">
<Logo/>
<Nav class="hidden-xs" :routings="routings"/>
<Button v-if="!isLoggedIn" class="hidden-xs" :label="isLoggedIn ? 'Console' : 'Login / Sign-up'" :isFilled="true" :action="goToLogin"/>
<UserWidget class="hidden-xs" v-if="isLoggedIn" :email="setFirstName" :title="'administrator'" :isUserMenu="true" :action="gotoDashboard"/>
<div class="mobile-menu-icon-wrapper visible-xs" #click="getMobileMenu">
<i v-if="isMenuExpanded" class="mobile-menu-icon close-icon"></i>
<i v-if="!isMenuExpanded" class="mobile-menu-icon expand-icons"></i>
</div>
<div class="mobile-menu-wrapper visible-xs" :class="{'expanded': isMenuExpanded}">
<div class="menu-overlay" #click="getMobileMenu"></div>
<!-- here is part of the magic -->
<!-- alternative one, update isMenuExpanded directly -->
<Nav :routings="routings" :eventBus="eventBus" :adminDetails="adminDetails" :isLoggedIn="isLoggedIn" #closeNav="isMenuExpanded = false"/>
<!-- alternative two, update isMenuExpanded using the closeNavBar method -->
<!--<Nav :routings="routings" :eventBus="eventBus" :adminDetails="adminDetails" :isLoggedIn="isLoggedIn" #closeNav="closeNavBar"/> -->
<div class="mobile-menu-icon-wrapper" #click="getMobileMenu">
<i v-if="isMenuExpanded" class="mobile-menu-icon close-icon"></i>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
...
methods: {
// alternative using method
closeNavBar() {
this.isMenuExpanded = false;
}
}
...
}
</script>
The navbar component will emit the event once the user clicks on any router-link (you can add the event in any other link or button)
<template>
<div class="nav-wrapper">
<nav>
<ul>
<li v-for="(route, index) in routings" :key="index">
<!-- emit the event to close the navBar -->
<!-- emit directly in the tag -->
<router-link :to="route.url" #click="$emit('closeNav')">{{route.name}}</router-link>
<!-- emit by using a method -->
<!--<router-link :to="route.url" #click="closeNavBarFromChild">{{route.name}}</router-link>-->
</li>
<li>
Blog
</li>
<li class="visible-xs">
<Button v-if="!isLoggedIn" :label="loginButtonLabel" :isFilled="true" :action="goToLogin"/>
<UserWidget v-else :email="setFirstName" :title="'administrator'" :isUserMenu="true" :action="gotoDashboard"/>
</li>
</ul>
</nav>
</div>
</template>
<script>
...
methods: {
closeNavBarFromChild() {
this.$emit('closeNav') // Emit the event that the parent is listening
}
}
...
</script>
I wrote two ways to use events, but they have the same effect.
I am making the jump from jQuery/WordPress to Vue and I am really loving it so far but very basic things can confuse the hell out of me. I am working on a project and I'm trying to do the coding work myself (not copy/paste code into my app) so I can force myself to learn it. I have been working on a dropdown menu system and got it working, but I know it's sloppy.
I was having trouble passing variables down to the methods section, so I couldn't seem to make my functions dynamic. So I had to repeat a lot of code to get it to work. I know there is a better way of doing this, I just don't understand what Vue wants from me. I kept getting 'variable is defined but not used' errors when I tried to pass information. I don't have the broken code anymore so I can't show that off, but I do have my working code.
I am hoping someone can critique my shit code and help me understand a more sleek way of doing this.
<template>
<div>
<div id="nav">
<nav>
<ul>
<li>
<a class="navButton" #click.prevent="mapsDrop">Maps <i class="fas fa-layer-group"></i></a>
<transition name="slide-fade">
<div class="dropDown" v-show="isMapsOpen">
Drop Down Menu
</div>
</transition>
</li>
<li>
<a class="navButton" #click.prevent="createDrop">Create <i class="fas fa-plus-circle"></i></a>
<transition name="slide-fade">
<div class="dropDown" v-show="isCreateOpen">
Drop Down Menu
</div>
</transition>
</li>
<li>
<a class="circle" #click.prevent="notificationsDrop"><i class="fas fa-bell"></i></a>
<transition name="slide-fade">
<div class="dropDown" v-show="isNotificationsOpen">
Notofications
</div>
</transition>
</li>
</ul>
</nav>
</div>
</div>
</template>
<script>
export default {
data() {
return{
isMapsOpen: false,
isCreateOpen: false,
isNotificationsOpen: false
}
},
methods: {
toggle() {
mutations.toggleNav();
},
mapsDrop() {
this.isMapsOpen = !this.isMapsOpen
if(this.isNotificationsOpen){
this.isNotificationsOpen = !this.isNotificationsOpen
}
if(this.isCreateOpen){
this.isCreateOpen = !this.isCreateOpen
}
},
createDrop() {
this.isCreateOpen = !this.isCreateOpen
if(this.isNotificationsOpen){
this.isNotificationsOpen = !this.isNotificationsOpen
}
if(this.isMapsOpen){
this.isMapsOpen = !this.isMapsOpen
}
},
notificationsDrop() {
this.isNotificationsOpen = !this.isNotificationsOpen
if(this.isCreateOpen){
this.isCreateOpen = !this.isCreateOpen
}
if(this.isMapsOpen){
this.isMapsOpen = !this.isMapsOpen
}
}
}
};
</script>
I'll repeat, this all works. I couldn't figure out how to get it to run in snippet mode, and I've stripped out some of the other parts so you don't have to dig through it.. I shouldn't have to create functions for each of my menus, right?
Thanks in advance.
Try having one data value and toggling with just that:
new Vue({
el: "#app",
data() {
return{
toggle: ""
}
},
})
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="nav">
<nav>
<ul>
<li>
<a class="navButton" #click.prevent="toggle = 'maps'">Maps <i class="fas fa-layer-group"></i></a>
<transition name="slide-fade">
<div class="dropDown" v-if="toggle === 'maps'">
Drop Down Menu
</div>
</transition>
</li>
<li>
<a class="navButton" #click.prevent="toggle = 'create'">Create <i class="fas fa-plus-circle"></i></a>
<transition name="slide-fade">
<div class="dropDown" v-if="toggle === 'create'">
Drop Down Menu
</div>
</transition>
</li>
<li>
<a class="circle" #click.prevent="toggle = 'notifications'"><i class="fas fa-bell"></i></a>
<transition name="slide-fade">
<div class="dropDown" v-if="toggle === 'notifications'">
Notifications
</div>
</transition>
</li>
</ul>
</nav>
</div>
</div>
Insert a unique value for each dropdown and then use v-if to determine if it contains the correct value.
i have been struggling for hours on this one, i am a newbie in vuejs basically i have a modal based on tabs and i want to show some data into the modal-content of my modal, the place where click event of open modal occurs is in another vue file and the place where i want to populate the modal content is in another vue,here's my code
main blade file
#section('main-content')
<div class="full-page-taps">
<div class="page-head p-4 mb-lg-4">
<h3>Directory</h3>
</div>
<div class="container">
<div class="row">
<div class="col-md-12">
<employee-search :inplaceholder="'Search Techs'"></employee-search>
</div>
</div>
<employee-card-section :indata="{{ $employees }}"></employee-card-section>
</div>
<modal name="employee-modal"
:width="'94%'"
:height="'94%'"
>
<employee-modal-content v-on:custom="customHandler"></employee-modal-content>
</modal>
</div>
#endsection
employeecard.vue
methods: {
openEmployee() {
// if(this.viewEmployees) {
this.$modal.show('employee-modal');
// this.$emit("passdata",this.employee.id);
this.$emit('chalja');
// this.$emit('custom', 'somedata');
// this.$eventHub.$emit("passdata");
// })
// }
}
},
employee-modal-content.vue
<template>
<div>
<div class="secondary-header no-margin">
<h2>UNEEB</h2>
</div>
<div class="customer-panel">
<input type="hidden" id="eid" value="" />
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#profile" role="tab">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#bio" role="tab">Bio</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#audit" role="tab">Audit</a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane active" id="profile" role="tabpanel">
</div>
<div class="tab-pane" id="bio" role="tabpanel">
</div>
<div class="tab-pane" id="audit" role="tabpanel">
</div>
</div>
</div>
</div>
</template>
<script>
export default {
methods:{
customHandler : function(e){
console.log(e);
console.log("works");
}
},
mounted(){
this.$eventHub.$on('chalja', ()=> {
alert("agya");
});
}
}
</script>
i basically want to pass in the ID from employeecard.vue to directory-modal-content.vue. i have tried many solutions but none worked for me, any help?
Should be so:
1.Pass your id as dynamic prop of component
<employee-modal-content :id="employee.id"></employee-modal-content>
2.In your child component u have to use props to receive the id variable
<template>
<div>
{{ id }}
</div>
</template>
<script>
export default {
props: ['id'],
methods:{
//...
}
}
</script>
I am new to Vue and created a basic authentication application.
AuthService.js
module.exports = {
isLoggedIn: function() {
if (localStorage.getItem("authUser") != null) {
return true;
} else {
return false;
}
},
Logout: function() {
localStorage.removeItem("authUser");
},
}
App.vue
<template>
<div id="app" >
<top-progress ref="topProgress"></top-progress>
<div class="nav is-light is-fixed-top">
<div class="container">
<span class="nav-toggle" v-on:click="toggleNav" v-bind:class="{ 'is-active': isActive }">
<span></span>
<span></span>
<span></span>
</span>
<div class="nav-right nav-menu" v-bind:class="{ 'is-active': isActive }">
<router-link v-ripple to="/" class="nav-item r-item"><i class="fa fa-home"></i>Home</router-link>
<router-link v-ripple to="faq" class="nav-item r-item"><i class="fa fa-file"></i>Features</router-link>
<router-link v-ripple to="dashboard" class="nav-item r-item"><i class="fa fa-dashcube"></i>Dashboard</router-link>
<router-link v-ripple to="faq" class="nav-item r-item"><i class="fa fa-quora"></i>Faq</router-link>
<a class="nav-item r-item" v-if="LoggedIn"><i class="fa fa-sign-out" #click.prevent="Logout"></i>Logout</a>
<div class="nav-item" v-if="!LoggedIn">
<p class="control">
<router-link to="login" class="button is-primary is-outlined">
<span class="icon">
<i class="fa fa-download"></i>
</span>
<span> Join Now</span>
</router-link>
</p>
</div>
</div>
</div>
</div>
<br>
<router-view></router-view>
<footer class="footer is-secondary">
<div class="container">
<div class="columns">
<div class="column">
<p>And this right here is a spiffy footer, where you can put stuff.</p>
</div>
<div class="column has-text-right">
<a class="icon" href="#"><i class="fa fa-facebook"></i></a>
<a class="icon" href="#"><i class="fa fa-twitter"></i></a>
</div>
</div>
</div>
</footer>
</div>
</template>
<script>
import {isLoggedIn,Logout} from "./service"
import miniToastr from 'mini-toastr'
import topProgress from 'vue-top-progress'
export default {
name: 'app',
components:{topProgress},
data:function(){
return {
isActive:false,
LoggedIn:false,
}
},
created(){
this.LoggedIn=isLoggedIn();
},
mounted(){
miniToastr.init()
this.$refs.topProgress.start()
setTimeout(() => {
this.$refs.topProgress.done()
}, 2000)
},
methods:{
Logout:function(){
Logout();
this.$router.push("login");
},
}
}
</script>
<style lang="sass">
..//
</style>
After successful login, I am using this.$router.push("home") to navigate to home component but the Login/Logout button not hiding/showing until I refresh the page.
The problem you are having is the created: hook is only called when App.vue is first created. Since this component holders the router-view it is always there as you move around the app — it's never destroyed, so it never needs to be created again. As a result your this.LoggedIn is only updated when you first load the app (or as you discovered, hit refresh).
You need to find a different way to update this.LoggedIn. One obvious possibility it to set it in the logih/logout methods.
Logout:function(){
Logout();
this.LoggedIn = isLoggedIn(); // or simply this.LoggedIn = false
this.$router.push("login");
},
It looks like users will login in a different component, so you will need to send an event from the child component to App.vue and trigger a method on App.vue to set this.LoggedIn when users login.
There are probably other possibilities that will come to mind now that you see why it isn't working.