Creating an Interactice timeline in Vue Js - vue.js

I am creating an interactive Timeline in Vue.js and have a base code set up. What currently happens is when you select a year, content shows up but to make it disappear you need to click it again.
What I am trying to do is make the content of the previous year disappear when you click another year.
The Codepen I created is linked below:
Vue JS Timeline
As you can see, my Vue JS code has different set ups for showing the data.
var vue = new Vue({
el:"#app",
data: {
nowShowing: false,
nowShowing2: false,
nowShowing3: false,
nowShowing4: false,
isShowing:false,
message: 'test1',
message2: 'test2',
message3: 'test3',
message4: 'test4',
message5: 'test5',
}});
Then going into the HTML you have a button class
<button class="c-History__year" #click="isShowing ^= true">1880</button>
And the div class:
<div v-show="isShowing">
<p class="c-History__summary">
{{message}}
</p>
</div>
Is this possible to complete in Vue with transitioning or would CSS suffice?

I've bundled all the isShowing variables into just one and the divs are now looking for whether the isShowing var has a specific number and when does, the div will be shown and all others will be hidden.
JS:
const vue = new Vue({
el:"#app",
data: {
showing: -1,
message: 'test1',
message2: 'test2',
message3: 'test3',
message4: 'test4',
message5: 'test5',
},})
HTML:
<div id="app">
<div class="o-Container o-Container--padded">
<div class="c-History">
<div class="c-History__timeline">
<div class="c-History__years">
<span class="c-History__line"></span>
<button class="c-History__year" #click="showing = 0">1880</button>
<button class="c-History__year" #click="showing = 1">1938</button>
<button class="c-History__year" #click="showing = 2">1971</button>
<button class="c-History__year" #click="showing = 3">1982</button>
<button class="c-History__year" #click="showing = 4">2007</button>
</div>
</div>
</div>
<transition name="bounce">
<div v-show="showing == 0">
<p class="c-History__summary">
{{message}}
</p>
</div>
</transition>
<transition name="bounce">
<div v-show="showing == 1">
<p class="c-History__summary">
{{message2}}
</p>
</div>
</transition>
<transition name="bounce">
<div v-show="showing == 2">
<p class="c-History__summary">
{{message3}}
</p>
</div>
</transition>
<transition name="bounce">
<div v-show="showing == 3">
<p class="c-History__summary">
{{message4}}
</p>
</div>
</transition>
<transition name="bounce">
<div v-show="showing == 4">
<p class="c-History__summary">
{{message5}}
</p>
</div>
</transition>
</div>
</div>
</div>

You can do it with a different a simpler approach, first you can change your data structure like this:
var vue = new Vue({
el:"#app",
data: {
message: 'test1',
message2: 'test2',
message3: 'test3',
message4: 'test4',
message5: 'test5',
contentToShow: ''
},
methods: {
showContent(messageIndex) {
this.contentToShow = this[messageIndex]
}
}
})
the idea is to have a method where you are going to pass the index of message property, and set only one visible contentToShow
So your component updated will be
<div id="app">
<div class="o-Container o-Container--padded">
<div class="c-History">
<div class="c-History__timeline">
<div class="c-History__years">
<span class="c-History__line"></span>
<button class="c-History__year" #click="showContent('message')">1880</button>
<button class="c-History__year" #click="showContent('message2')">1938</button>
<button class="c-History__year" #click="showContent('message3')">1971</button>
<button class="c-History__year" #click="showContent('message4')">1982</button>
<button class="c-History__year" #click="showContent('message5')">2007</button>
</div>
</div>
</div>
<transition name="bounce">
<div v-show="contentToShow">
<p :key="contentToShow" class="c-History__summary">
{{contentToShow}}
</p>
</div>
</transition>
</div>
</div>
</div>

Related

Font awesome class icons toggling not working Vue

So I am working on the signup form using Vue.js and there is this password part that I want the user to view password and toggle back to unseen password I have both font awesome icons (fas fa-eye and fa-solid fa-eye-slash) but the state only remains the same even after toggling see the password. I tried with text options SEE and HIDE and it worked but the icons are not
My Code :
<div class="field">
<div class="textbox">
<div #click="viewPassword()">
<span v-if="showPassword !== true">
<i class="fas fa-eye"></i>
SEE
</span>
<span v-else>
<i class="fa-solid fa-eye-slash"></i>
HIDE
</span>
</div>
<input
:type="showPassword ? 'text' : 'password'"
:placeholder="$t('common.PASSWORD')"
data-cy="walletPassword"
name="walletPassword"
v-model="walletPassword"
autocomplete="off"
/>
</div>
</div>
Functional code
export default class Login extends mixins(Global, Recaptcha) {
// Component properties
walletEmail = '';
walletPassword = '';
showRecovery = false;
logonError = '';
showPassword = false;
viewPassword() {
this.showPassword = !this.showPassword;
}
}
Observations :
Dynamic :type assignment will give compiling template error. Hence, will suggest to use v-if/v-else clause.
Just to make it clean, You can use v-if="!showPassword" instead of v-if="showPassword !== true".
Live Demo :
new Vue({
el: '#app',
data: {
showPassword: false,
walletPassword: null
},
methods: {
viewPassword() {
this.showPassword = !this.showPassword;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css"/>
<div id="app">
<div #click="viewPassword()">
<span v-if="!showPassword">
<i class="fas fa-eye"></i>
</span>
<span v-else>
<i class="fa-solid fa-eye-slash"></i>
</span>
</div>
<input v-if="showPassword" type="text" name="walletPassword" v-model="walletPassword" autocomplete="off"/>
<input v-else type="password" name="walletPassword" v-model="walletPassword" autocomplete="off"/>
</div>

vue accordion prevents events from firing on click

I just started learning Vue2.
I use bootstrap accordion.
I want to be able to click the 'hello button' without triggering the 'collapse' event.
How to do this?
<template>
<div class="accordion" id="accordionExample">
<div class="accordion-item" v-for="i in 3" :key="i">
<h2 class="accordion-header" :id="`headingOne${i}`">
<button class="accordion-button"
type="button" data-bs-toggle="collapse"
:data-bs-target="`#collapseOne${1}`"
aria-expanded="true"
:aria-controls="`collapseOne${1}`"
>
Accordion Item #{{ i }}
<button class="btn-primary" #click=test>hello button</button>
</button>
</h2>
<div :id="`collapseOne${i}`" class="accordion-collapse show"
:aria-labelledby="`headingOne${i}`">
<div class="accordion-body">
<strong>This is the first item's accordion body.</strong>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Learn',
methods: {
test () {
console.log('hello')
}
}
}
</script>
You have to make sure that your hello-button is not nested inside the accordion-button. Just put both buttons right next to eachother. You might have to adjust the css to position them properly.
<template>
<div class="accordion" id="accordionExample">
<div class="accordion-item" v-for="i in 3" :key="i">
<h2 class="accordion-header" :id="`headingOne${i}`">
<button class="accordion-button"
type="button" data-bs-toggle="collapse"
:data-bs-target="`#collapseOne${1}`"
aria-expanded="true"
:aria-controls="`collapseOne${1}`"
>
Accordion Item #{{ i }}
</button>
<button class="btn-primary" #click=test>hello button</button>
</h2>
<div :id="`collapseOne${i}`" class="accordion-collapse show"
:aria-labelledby="`headingOne${i}`">
<div class="accordion-body">
<strong>This is the first item's accordion body.</strong>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Learn',
methods: {
test () {
console.log('hello')
}
}
}
</script>

Vue Js v-for using

I'm a vue.js beginner. I want to get data from app.js using v-for in html and show it in separate divs. I want to add an independent background and an independent text for each todo.
var example = new Vue({
el:"#example",
data: {
todos : [
{id:1 , name: "ŞEHİR MERKEZİ"},
{id:2 , name: "HÜDAİ KAPLICA"},
{id:3 , name: "AFYONKARAHİSAR"}
]
}
})
<div class="container" id="example">
<div class="row">
<div class="col-lg-6">
<div class="flip flip-vertical">
<div
class="front"
style="background: url(./static/images/sandıklı.jpg)">
<h1 class="text-shadow" >
<div class="hborder" v-for="todo in todos" :key="todo">
{{todo.name}}
</div>
</h1>
</div>
<div class="back">
<h4>ŞEHİR MERKEZİ GÜZERGAHINI ONAYLIYOR MUSUNUZ ?</h4>
<button type="button" class="btn btn-primary btn-lg">EVET</button>
<button type="button" class="btn btn-danger btn-lg">HAYIR</button>
</div>
</div>
</div>
</div>
</div>
<script src="./static/js/vue#2.js"></script>
<script src="./static/js/app.js"></script>
what you could do is add the background color and description to the todos object.
Also I made a little change in your data function.
var example = new Vue({
el:"#example",
data() {
return {
todos : [
{id:1 , name: "ŞEHİR MERKEZİ", bg: '#FFF', desc: 'desc1'},
{id:2 , name: "HÜDAİ KAPLICA", bg: '#ff0000', desc: 'desc2'},
{id:3 , name: "AFYONKARAHİSAR", bg: '#cecece', desc: 'desc3'}
]
}
}
})
<div class="container" id="example">
<div class="row">
<div class="col-lg-6">
<div class="flip flip-vertical">
<div
class="front"
style="background: url(./static/images/sandıklı.jpg)">
<h1 class="text-shadow" >
<div class="hborder" v-for="todo in todos" :key="todo" :style="background-color: todo.bg;">
{{todo.name}}
{{todo.desc}}
</div>
</h1>
</div>
<div class="back">
<h4>ŞEHİR MERKEZİ GÜZERGAHINI ONAYLIYOR MUSUNUZ ?</h4>
<button type="button" class="btn btn-primary btn-lg">EVET</button>
<button type="button" class="btn btn-danger btn-lg">HAYIR</button>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2"></script>

Pagination in vue.js framework

Error with Pagination in vue.js framework in view page, The Pagination bar is working fine but I have 50 records on the same page. The Pagination bar is 17 => 50/3 . The Post is displayed in div section not in Table.
<template>
<div class="blog">
<h2>{{ pageDescreption }}</h2>
<hr />
<div class="alert alert-success" role="alert" v-text="alertTitel"></div>
<div class="row">
<div class="col-md-8">
<div class="posts-area">
<PostList
id="PostList"
v-for="post in posts"
:key="post.id"
:post="post"
:current-page="currentPage"
:per-page="perPage"
/>
<div class="overflow-auto">
<b-pagination
v-model="currentPage"
:total-rows="rows"
:per-page="perPage"
aria-controls="PostList"
></b-pagination>
<p class="mt-3">Current Page: {{ currentPage }}</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import PostList from "#/components/Blogs/PostList.vue";
import PostJson from "../Gatewaye/post.json";
export default {
data: function() {
return {
pageName: "blog",
pageDescreption: "This is an Blog page",
alertTitel: "List of all Posts",
posts: PostJson, // array of posts [50 records]
perPage: 3,
currentPage: 1
};
},
name: "Blog",
components: {
PostList
},
computed: {
rows() {
return this.posts.length;
}
}
};
</script>
And in Components file Blog.vue is:
<template>
<div class="PostList">
<div class="post-container text-left">
<span class="post-views badge badge-primary" title="Views">{{
post.views
}}</span>
<h3 class="post-title" title="Title">{{ post.title }}</h3>
<span class="post-date" title="Date">{{ post.date }}</span>
<p class="post-body">
{{ post.contant }}
</p>
<div class="row">
<div class="col-sm-6">
<span class="post-author" title="Auther">{{ post.auther }}</span>
</div>
<div class="col-sm-6 text-right">
<span class="post-category" title="Category">{{
post.category
}}</span>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ["post"],
name: "PostList"
};
</script>
The Pagination bar is working fine but I have 50 records on the same page ... Thank you
Use a computed property to slice the post array in the parent component:
computed: {
paginatedposts() {
return this.posts.slice(this.perPage*(this.currentPage-1), (this.perPage*(this.currentPage-1))+this.perPage);
}
}
Now you just need to bind this computed property:
<PostList
id="PostList"
v-for="post in paginatedposts"
:key="post.id"
:post="post"
/>

(Vue.js) modal close event

When I click on the outer area of ​​the modal, I want the same event as the close button of the modal. (Event that closes modal when clicking outside area of ​​modal)
The current progress is that the modal is closed when the close modal button is clicked.
Carousel.vue
<template>
<div>
<div v-for="(item, index) in photos" :key="index">
<div #click="imgClick(item)" style="cursor:pointer;">
<img :src="item.thumbnail" />
</div>
<Modal v-if='item.show' #close="item.show = false">
<div slot='body'>
<img :src="item.thumbnail" :class="`img-index--${index}`"/>
</div>
</Modal>
</div>
</div>
</template>
<script>
import Modal from './Modal.vue'
export default {
props: {
items: { type: Array, default: () => [] }
},
data() {
return {
photos: {}
}
},
created() {
this.photos = this.items.map(item => {
return { ...item, show: false }
})
},
methods: {
imgClick(item) {
item.show = true
}
},
components: {
Modal: Modal
}
}
</script>
Modal.vue
<template>
<transition name="modal">
<div class="modal-mask" #click="$emit('close')">
<div class="modal-wrapper">
<div class="app__phone">
<div class="feed">
<div class="post">
<div class="header headroom">
<div class="level-left">
<img src="../assets/imgs/user.gif" class="modal-header-img"/>
<div class="user">
<span class="username">username</span>
<button class="modal-default-button" #click="$emit('close')">Close</button>
</div>
</div>
</div>
<slot name="modal-img"></slot>
<div class="content">
<div class="content-title">
<slot name="modal-tit"></slot>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</transition>
</template>
When I add a click event to the bottom <div>, it closes when I click outside the modal, but it closes when I click anywhere in the modal.
<div class="modal-mask" #click="$emit('close')">
And this link has a Fiddle example in the accepted answer to the question.
https://stackoverflow.com/a/58023701/12066654
You need to add a handler to the outer modal div like so:
<template id="modal">
<div class="modal" #click.self="close">
<div class="close" #click="close">×</div>
<div class="body">
<slot name="body" />
</div>
</div>
</template>