link1918 link1919 link1920 link1921 link1922 link1923 link1924 link1925 link1926 link1927 link1928 link1929 link1930 link1931 link1932 link1933 link1934 link1935 link1936 link1937 link1938 link1939 link1940 link1941 link1942 link1943 link1944 link1945 link1946 link1947 link1948 link1949 link1950 link1951 link1952 link1953 link1954 link1955 link1956 link1957 link1958 link1959 link1960 link1961 link1962 link1963 link1964 link1965 link1966 link1967 link1968 link1969 link1970 link1971 link1972 link1973 link1974 link1975 link1976 link1977 link1978 link1979 link1980 link1981 link1982 link1983 link1984 link1985 link1986 link1987 link1988 link1989 link1990 link1991 link1992 link1993 link1994 link1995 link1996 link1997 link1998 link1999 link2000 link2001 link2002 link2003 link2004 link2005 link2006 link2007 link2008 link2009 link2010 link2011 link2012 link2013 link2014 link2015 link2016 link2017 link2018 link2019 link2020 link2021 link2022 link2023 link2024 link2025 link2026 link2027 link2028 link2029 link2030 link2031 link2032 link2033 link2034 link2035 link2036 link2037 link2038 link2039 link2040 link2041 link2042 link2043 link2044 link2045 link2046 link2047 link2048 link2049 link2050 link2051 link2052 link2053 link2054

[Vue.js] Routing via Laravel API

there is a very small software and I use laravel and vue.js. I would like to know the difference between routing though api.php and web.php in routes folder. Can somebody explain me the difference in these two cases?

Solution :

You can define the routes in either web.php or api.php. However, routes in api.php have certain advantages

routes get automatically prefixed with ‘/api/‘
routes use api-middleware and auth. This can add certain additional security by throttling API-requests.

You should use api.php for all the api needs or any routes that will be called through ajax.

:

[Vue.js] vue.js and firebase query giving wrong array count

something weird is going on. when using Vue.js and Firebase. my query is simple. there is 3 documents in the database

let tagRef = db.collection(‘tags’)
tagRef = tagRef.where(‘gid’, ‘==’, this.$store.getters.gid)
tagRef.onSnapshot(snapshot => {
this.tags = []
snapshot.docChanges().forEach(change => {
let docs = change.doc
this.tags.push(docs.data())
console.log(this.tags.length)
})
})

as you can see when logging the array length to the console. when I refresh the page my console log reads 1 1 2 however when a change is made is reads correctly 1 2 3

when not sure why it is doing this.

When I change the console.log from this.tags.length to this.tags attached are the screen shots of what I get.

on page refresh

when a change occurs

any help is greatly appreciated.

UPDATE:

This is a game. players can tag each other. when a player gets tagged they are disabled temporarily until their tag is complete. the second piece is each player can be tagged no more than 3 times.

In the created() hook I query for the tags and when using the realtime part of firebase so anytime something changes with the tag database the code is updated.

there is a method as seen below:

countTags(team) {
return this.tags.filter(function (tag) {
if(tag.tagged == team.team_id){
return team
}
})
},

This method is supposed to return the tags based off of the team id. i the html there is this

:class=”{‘taglimit’ : countTags(team).length >= 3}”

which will add the “taglimit” class if the count is 3 or greater.

SECOND UPDATE:

When I run this query in the created hook there is issues

let tagRef = db.collection(‘tags’)
tagRef = tagRef.where(‘gid’, ‘==’, this.$store.getters.gid)
tagRef.onSnapshot(snapshot => {
this.tags = []
snapshot.docChanges().forEach(change => {
let docs = change.doc
this.tags.push(docs.data())
})
})

but when I run this query I don’t

let tagRef = db.collection(‘tags’)
tagRef = tagRef.where(‘gid’, ‘==’, this.$store.getters.gid)
tagRef.get().then((snapshot) => {
snapshot.forEach(doc => {
let tag = doc.data()
tag.id = doc.id
this.tags.push(tag)
})
}).catch(err => {
console.log(err)
})

The problem is I need to update the code every time the tag database changes.

THIRD UPDATE

I think I found the issue. I moved this.tags = [] outside the query and everything appears to be working fine now. so now the query looks like this.

this.tags = []
let tagRef = db.collection(‘tags’)
tagRef = tagRef.where(‘gid’, ‘==’, this.$store.getters.gid)
tagRef.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
let docs = change.doc
this.tags.push(docs.data())
console.log(this.tags.length)
})
})

FOURTH UPDATE:

here is the HTML

<v-dialog v-model=”dialog” persistent transition=”scale-transition” fullscreen light>
<v-btn
slot=”activator”
fixed
dark
fab
bottom
right
color=”blue-grey darken-2”
class=”pulse-button”
\>
<v-icon>directions_run</v-icon>
</v-btn>
<v-card color=”rgba(224, 224, 224, .95)”>
<v-container grid-list-md text-xs-center>
<v-layout row wrap class=”tagform-container”>
<v-btn dark fab right absolute small color=”grey darken-3” @click=”dialog = false”><v-icon>close</v-icon></v-btn>
<v-layout justify-center>
<v-card-title class=”display-2 font-weight-black”>TAG!</v-card-title>
</v-layout>
<v-card-text class=”subheading”>Select a team you want to tag. Note, you only have one tag per game. Use it wisely!</v-card-text>
<v-flex xs4 class=”add-flex” v-for=”team in activeTeams” :key=”team.id” >
<div class=”tag-card”
:class=”{‘disabled’ : activeTag(team).length > 0, ‘taglimit’ : countTags(team).length >= 3}”
height=”100%”
color=”white”
style=”background:#fff;”
@click=”activeTag(team).length > 0 || countTags(team).length >= 3 ? ‘’ : selectedTeam(team)”
\>
<v-layout justify-center>
<v-card-title class=”title”>{team.team_name}</v-card-title>
</v-layout>
<v-responsive>
<img class=”avatar” v-bind:src=”team.url”>
</v-responsive>
<v-flex>
<v-card-text class=”body-2 text-uppercase”>Tap to select</v-card-text>
</v-flex>
</div>
</v-flex>
</v-layout>
</v-container>
</v-card>
</v-dialog>

There is more but this is the part that counts.

Here is some more of the code

data() {
return {
feedback: null,
teams: [],
taggedteam: null,
dialog: false,
stepper: false,
emojiinput: ‘’,
search: ‘’,
e1: 1,
tag: null,
tags: [],
completedtags: [],
tagstates: []
}
},
computed: {
activeTeams: function () {
let thisTeam = this.$store.getters.player.team_id
return this.teams.filter(function (team) {
if(team.team_id !== thisTeam)
return team
})
}
},

One of the Methods:

countTags(team) {
return this.tags.filter(function (tag) {
if(tag.tagged == team.team_id){
return team
}
})
},

finally the created hook

created(){
// get teams
let teamRef = db.collection(‘teams’)
teamRef = teamRef.where(‘gid’, ‘==’, this.$store.getters.gid)
teamRef = teamRef.orderBy(‘team_id’)
teamRef.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if(change.type == ‘added’) {
let docs = change.doc

let leaderRef = db.collection(‘leaderboard’)
leaderRef = leaderRef.where(‘gid’, ‘==’, this.$store.getters.gid)
leaderRef = leaderRef.where(‘team’, ‘==’, docs.data().team_id)
leaderRef = leaderRef.where(‘missioncomplete’, ‘==’, true)
leaderRef.onSnapshot(snapshot => {
if(snapshot.empty) {
// team has not completed the mission so they can still be tagged
this.teams.push(docs.data())
}
})

}
})
})

// get tags
this.tags = []
let tagRef = db.collection(‘tags’)
tagRef = tagRef.where(‘gid’, ‘==’, this.$store.getters.gid)
tagRef.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
let docs = change.doc
this.tags.push(docs.data())
})
})

// get tag states
this.tagstates = []
let tagStateRef = db.collection(‘tagstate’)
tagStateRef = tagStateRef.where(‘gid’, ‘==’, this.$store.getters.gid)
tagStateRef = tagStateRef.where(‘state’, ‘==’, true)
tagStateRef = tagStateRef.orderBy(‘tag’)
tagStateRef.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
let docs = change.doc
this.tagstates.push(docs.data())
})
})

if(this.$store.getters.player.team_id) {
// check to see if this player has already tagged someone
let tagRef = db.collection(‘tags’)
tagRef = tagRef.where(‘tagger’, ‘==’, this.$store.getters.player.team_id)
tagRef = tagRef.where(‘gid’, ‘==’, this.$store.getters.gid)
tagRef.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
let docs = change.doc
this.completedtags.push(docs.data())
})
})
}
}

Solution :

It’s a bit difficult to dive into the code without knowing the exact relationship between teams/tags and their respective limits.

But I’ve understood from the discussion that you want to change the class of a DOM element if the result of the query is more that 3 documents.

You’ll find a possible approach below, which shows how to manange the class change (and also, if needed how to maintain the tags array in the data object, i.e. being reactive to database changes).

<template>
<div :class=”{ taglimit: isTagLimit }”>Test</div>
</template>

<script>
const fb = require(“../firebaseConfig.js”);
export default {
data() {
return {
tags: [],
isTagLimit: false
};
},

created: function() {
let tagRef = fb.db.collection(“tags”);
tagRef = tagRef.where(“gid”, “==”, this.$store.getters.gid);
tagRef.onSnapshot(querySnapshot => {
console.log(querySnapshot.size);
//The next if is sufficient to activate the taglimit class
if (querySnapshot.size > 3) {
this.isTagLimit = true;
} else {
this.isTagLimit = false;
}
//If you want to update the tags property
var t = [];
querySnapshot.forEach(doc => {
t.push(doc.data());
});
this.tags = t;
});
}
};
</script>

<style>
.taglimit {
color: deeppink;
}
</style>

Note that instead of replacing the entire tags array, you could listen to “atomic” changes in the Query and update the array with the changes, see https://firebase.google.com/docs/firestore/query-data/listen#view\_changes\_between\_snapshots

[Vue.js] Problem re-rendering vue instance when data is changed by a call-back inside a method

I’m developing a app with electron using vue.js as a standalone libray (no CLI envolved) and it get a pretty wird re-rendering behavior when I change data by a call-back of a electron method inside a vue.js method (rendering on a v-for). I show a simplified code:

<div class=”list-item” v-for=”(filePath, index) in playlistArray”>
<div class=”audio-file-index”> { index + 1 } </div>
<div class=”audio-file-name”> { filePath } </div>
</div>

const { remote } = require(‘electron’);

let vue.js = new Vue({
el: ‘#app’,
data: {
playlistArray: [‘’, ‘’, ‘’, ‘’, ‘’]
// could just ‘= Array(5)’ but i need ‘’ elements so the v-for renders 5
// empty divs right away
},
methods: {
addAudioFile() {

remote.dialog.showOpenDialog({ // electron.remote method to let user select files

//… doesn’t metter, just a options object….

}, (pathArray) => {
// pathArray returns a array with all paths selected by the user

let j = 0;
for(i = 0; i < this.playlistArray.length; i++) {
if(this.playlist[i] == ‘’) {
this.playlistArray[i] = pathArray[i + j];
j++;
}
}
})
}
}
})

Ok so when the user select audio files the divs show the path and (index + 1) of each path.

First thing I don’t get: after the first call of addAudioFile( ), all the ‘ ‘ elements of playlistArray turns to undefined, so I had to change the if statemant to:

if(this.playlistArray[i] == ‘’ || this.playlistArray[i] == undefined)

Why is it changing? (If the array has a element with a truthy string it doesen’t change to undefined). But ok…

The wird behavior: v-for doesn’t re-render when playlistArray is changed… but…If I toogle the developers tools, close it, and click anywhere in my app the re-rendering works (?).

I changed the code using another help method and a help variable:

let vue.js = new Vue({
el: ‘#app’,
data: {
playlistArray: [‘’, ‘’, ‘’, ‘’, ‘’]
},
methods: {
addAudioFile() {

remote.dialog.showOpenDialog({

}, (pathArray) => {
let j = 0;
let newPlaylistArray = [];

for(i = 0; i < this.playlistArray.length; i++) {
if(this.playlist[i] == ‘’ || this.playlistArray[i] == undefined) {
newPlaylistArray[i] = pathArray[0 + j];
j++;
}
else newPlaylistArray[i] = this.playlistArray[i] || ‘’;
}
this.updatePlaylist(newPlaylistArray);
})
},

updatePlaylist(playlist) {
this.playlistArray = playlist;
}
}
})

… and now it works properly. Why?

Solution :

My guess is because of reactivity. As the documentation says:

vue.js cannot detect the following changes to an array:

When you directly set an item with the index, e.g.
vm.items[indexOfItem] = newValue

Source

To make the first example work, you can try the splice or set methods:

for(i = 0; i < this.playlistArray.length; i++) {
if(this.playlist[i] == ‘’) {
this.playlistArray.splice(i, 1, pathArray[i + j])
// or
this.$set(this.playlistArray, i, pathArray[i + j])
j++;
}
}

Note: you use this condition if(this.playlist[i] == ‘’). Where playlist property comes from ? Do you mean playlistArray instead ?

[Vue.js] Trying to set Vue Meta page title using string + variable

I’m using vue.js Meta as part of a blog application within a project using Nuxt JS 2.4.5

I’m having some trouble trying to set the title + a variable from data () and I’m not sure what I’m missing

I’ve tried multiple attempts at getting it to work, moving code around, using this setting it manually, nothing seems to work…

<script>
import BlogsFromJson from ‘~/static/articles/blogs.json’;

export default {
head: {
title: ‘My Website: Blog: ‘ + this.myBlogTitle, // or something else
meta: [
{ hid: ‘description’, name: ‘description’, content: ‘Read the latest news and articles from Flex Repay UK.’ }
]
},
data () {
return {
title: this.$route.params.title,
blog: BlogsFromJson,
myBlogTitle: ‘some title’
}
}
}
</script>

I’ve tried setting a variable within data () and using it statically.

Doing this should give me My Website: Blog: some title

What could I be missing here?

Solution :

Instead of defining metaInfo as an object, define it as a function and access this as usual:

Post.vue:

<template>
<div>
<h1>[Vue.js] Trying to set Vue Meta page title using string + variable</h1>
</div>
</template>

the script

<script>
export default {
name: ‘post’,
props: [‘title’],
data () {
return {
description: ‘A blog post about some stuff’
}
},
metaInfo () {
return {
title: this.title,
meta: [
{ vmid: ‘description’, name: ‘description’, content: this.description }
]
}
}
}
</script>

PostContainer.vue:

<template>
<div>
<post :title=”title”></post>
</div>
</template>

<script>
import Post from ‘./Post.vue’

export default {
name: ‘post-container’,
components: { Post },
data () {
return {
title: ‘Example blog post’
}
}
}
</script>

Solution 2:

Try to use function instead of object for head.
Change

head: {

},

to

head () {
return {

}
}

[Vue.js] Return value from dataPointSelection event in Apexcharts

there is a question related to this question and this answer but they don’t solve my question completely. I’m using vue.js and apexcharts and I would like to return a value or update a variable from an event. Is it possible to return something instead of printing it in the console?

Something like this:

events: {
dataPointSelection: function (event, chartContext, config) {
this.active = this.series[config.seriesIndex];
}
}

The problem that I face is that “this” makes reference to the overall vue.js component and therefore “series” and “active” cannot be found.

Here is the code that gives me”TypeError: this.series is undefined” when I click on a point data. The series data I get from the parent component and it looks like this:

[{“name”:”S-1”,”data”:[[2.65,100], [6.67,100]]}, {“name”:”S-2”,”data”:[[0,50],[2.65,50]]}]

<script>
import VueApexCharts from ‘vue-apexcharts’;

export default {
name: “myGraph”,
components: {
apexchart: VueApexCharts,
},
props: {
series: {}
},
data: () => ({
active: undefined,
chartOptions: {
chart: {
width: ‘100%’,
animations: {
enabled: false
},
events: {
dataPointSelection: function (event, chartContext, config) {
this.active = this.series[config.seriesIndex];
}
}
},
tooltip: {
intersect: true,
shared: false
},
markers: {size: 1},
}
}),
}
}
</script>

The idea is that on dataPointSelection, it should activate that serie in order to access later on other information that will be store in that object.

Solution :

The easiest way is to bind the event directly in the component

<apexchart type=”bar” @dataPointSelection=”dataPointSelectionHandler”></apexchart>

methods: {
dataPointSelectionHandler(e, chartContext, config) {
console.log(chartContext, config)
}
}

Another way is to use ES6 arrow functions in the chart configuration

computed: {
chartOptions: function() {
return {
chart: {
events: {
dataPointSelection: (e, chart, opts) => {
// you can call vue.js methods now as “this” will point to the vue.js instance when you use ES6 arrow function
this.VueDemoMethod();
}
}
},
}
}
}

[Vue.js] How passing data to a button in vue native?

I try to pass each button a title that is browsed in a loop. there is hard value, I can not get my true value.

I try this to passing to pass my variable like this to the title tag title

<view v-for=”(post, index) in posts” :key=”index”>
<button
:title=”post.name”
color=”#841584”
/>
</view>

As a result in my buttons there is “post.name” and the true value of my loop instead.

Solution :

If you are looking to bind the button name from the for loop
you can bind it like this

<button :title=”post.name”
color=”#841584”>{post.name}</button>

[Vue.js] Why does a reload return an empty state half of the time?

I’m creating a webshop for a hobby project in Nuxt 2.5. In the Vuex store there is a module with a state “currentCart”. In here I store an object with an ID and an array of products. I get the cart from the backend with an ID, which is stored in a cookie (with js-cookie).

I use nuxtServerInit to get the cart from the backend. Then I store it in the state. Then in the component, I try to get the state and display the number of articles in the cart, if the cart is null, I display “0”. This gives weird results. Half of the time it says correctly how many products there are, but the Vuex dev tools tells me the cart is null. The other half of the time it displays “0”.

At first I had a middleware which fired an action in the store which set the cart. This didn’t work consistently at all. Then I tried to set the store with nuxtServerInit, which actually worked right. Apparently I changed something, because today it gives the descibed problem. I can’t find out why it produces this problem.

The nuxtServerInit:

nuxtServerInit ({ commit }, { req }) {
let cartCookie;

// Check if there’s a cookie available
if(req.headers.cookie) {

cartCookie = req.headers.cookie
.split(“;”)
.find(c => c.trim().startsWith(“Cart=”));

// Check if there’s a cookie for the cart
if(cartCookie)
cartCookie = cartCookie.split(“=”);
else
cartCookie = null;
}
// Check if the cart cookie is set
if(cartCookie) {

// Check if the cart cookie isn’t empty
if(cartCookie[1] != ‘undefined’) {
let cartId = cartCookie[1];

// Get the cart from the backend
this.$axios.get(`${api}/${cartId}`)
.then((response) => {
let cart = response.data;
// Set the cart in the state
commit(“cart/setCart”, cart);
});
}
}
else {
// Clear the cart in the state
commit(“cart/clearCart”);
}
},

The mutation:

setCart(state, cart) {
state.currentCart = cart;
}

The getter:

currentCart(state) {
return state.currentCart;
}

In cart.vue:

if(this.$store.getters[‘cart/currentCart’])
return this.$store.getters[‘cart/currentCart’].products.length;
else
return 0;

The state object:

const state = () => ({
currentCart: null,
});

I put console.logs everywhere, to check where it goes wrong. The nuxtServerInit works, the commit “cart/setCart” fires and has the right content. In the getter, most of the time I get a null. If I reload the page quickly after another reload, I get the right cart in the getter and the component got the right count. The vue.js dev tool says the currentCart state is null, even if the component displays the data I expect.

I changed the state object to “currentCart: {}” and now it works most of the time, but every 3/4 reloads it returns an empty object. So apparently the getter fires before the state is set, while the state is set by nuxtServerInit. Is that right? If so, why is that and how do I change it?

What is it I fail to understand? I’m totally confused.

Solution :

So, you know that moment you typed out the problem to ask on Stackoverflow and after submitting you got some new ideas to try out? This was one of them.

I edited the question to tell when I changed the state object to an empty object, it sometimes returned an empty object. Then it hit me, the getter is sometimes firing before the nuxtServerInit. In the documentation it states:

Note: Asynchronous nuxtServerInit actions must return a Promise or leverage async/await to allow the nuxt server to wait on them.

I changed nuxtServerInit to this:

async nuxtServerInit ({ commit }, { req }) {

await this.$axios.get(`${api}/${cartId}`)
.then((response) => {

}
await commit(“cart/clearCart”);

So now Nuxt can wait for the results. The Dev Tools still show an empty state, but I think that is a bug, since I can use the store state perfectly fine in the rest of the app.

[Vue.js] Bootstrap-vue textarea.selectionStart is NaN or undefined

I’m trying to detect when the user is pressing the tab key, so I can insert spaces, instead of shifting the element focus.

The event handler is called correctly, but the value of both .selectionStart and .selectionEnd properties are either undefined or NaN. Is there something wrong with my code?

<b-form-textarea
id=”pythonCodeInput”
placeholder=”Write Python code here…”
v-model=”newQuestion.objects.code”
ref=”codeInput”
@keydown.native.tab=”keyDownInTextarea”>
</b-form-textarea>

Relevant code from keyDownInTextarea

let codeInput = this.$refs.codeInput;

// Add 4 spaces
let tabSize = 4;
let tabPosition = codeInput.selectionStart;
let textWithSpaces = codeInput.value.substring(0, tabPosition);
for (let i = 0; i < tabSize; i++) textWithSpaces += “ “;
textWithSpaces += codeInput.value.substring(tabPosition);

I expect tabPosition to have an value showing where the cursor is, but the actual output is NaN or undefined.

Solution :

When you attached a ref to <b-form-textarea>, what you get is the reference to an instance of the <b-form-textarea> component and not the textarea element which you are trying to access. Refer to
docs for more info.

To access the actual <textarea> element, you can do it by accessing the inner $refs of the codeInput ref since under the hood, the textarea element has a ref called input.

To put it simply, it would look like this.

// this is a reference to the `<b-form-textarea>` component instance.
let codeInput = this.$refs.codeInput;

// get the actual DOM element
const textArea = codeInput.$refs.input;

See working example

Solution 2:

I’m new to vue.js so sry if I got something wrong.

Here is what I got after some testing. I replaced @keydown.native.tab with v-on:keydown.tab and that seems to work without any problems.

new Vue({
el: ‘textarea’,
methods: {
test: (e) => {
console.log(e.target.selectionStart);
}
}
})
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<textarea
id=”textarea”
v-on:keydown.tab=”test” ></textarea>

[Vue.js] How to override padding 0; from sass?

when working on the footer of my website right now and when trying to make it responsive. Whenever the screen size gets smaller then 992px I made a media query, so the content of the footer gets centered inside the footer. Before it gets resized there is a column that I put padding: 0; on.

My problem is that I need that padding to be gone in order to center my content, but I need it for the normal sized footer. How can I override the padding: 0; so I can center my content?

Code for normal footer:

.social-media {
margin-bottom: 50px;

\> ul {
padding: 0;
list-style: none;

\> li {
\> a {
padding-right: 20px;
float: left;
color: #ffffff;
}
}
}
}

Code for the small footer:

@media screen and (max-width: 992px) {
.social-media {
margin-bottom: 0;
height: auto;
width: auto;

\> ul {
list-style: none;
text-align:center;

\> li {
padding-left: 10px;
padding-right: 10px;

\> a {}
}
}

}
}

The code for my bootstrap column:

<div class=”col-lg-3 offset-lg-6 social”>
<div class=”social-media”>
<ul class=”nav-items”>
<li class=”nav-item” :key=”index” v-editable=”item” v-for=”(item, index) in $store.state.settings.footer_nav”>
<LinkType class=”nav-link” :link=”item.link” :linkText=”item.name”>{ item.name }</LinkType>
</li>
</ul>
</div>
</div>

I hope someone can help me with this problem. I’ve been stuck on this for a while now.

Solution :

You can use ‘!important’ to enforce css properties.

.social-media
{
margin-bottom: 50px;

\> ul
{
padding: 10px !important;
list-style: none;

\> li
{

\> a
{
padding-right: 20px;
float: left;

color: #ffffff;
}
}
}
}

@media screen and (max-width: 992px) {

.social-media
{

margin-bottom: 0;

height: auto;
width: auto;

\> ul
{
list-style: none;

text-align:center;

\> li
{
padding-left: 10px;
padding-right: 10px;

\> a
{

}
}
}

}

[Vue.js] Vue.js Problem Controlling Div with v-show

there is four buttons and corresponding four divisions. On clicking first button, to display first div, on clicking the second button, to display the second div, and so on.

The button click event calls a method with the division number (0 through 3)
@click=”showDiv(0)” for first button and @click=”showDiv(1)” for the second button. This is my showDiv() method
showDiv: function(divNumber)

showDiv: function(divNumber)
{
this.showDetailsDiv.forEach(function(item, index, array) {
array[index]=null;
});
this.showDetailsDiv[divNumber] = true;
console.log(this.ShowDetailsDiv);
}

The initial value of showDetailsDiv prop is array with null values

showDetailsDiv: [
null,
null,
null,
null
],

In template, when trying to control the divisions through v-show

<div v-show=”showDetailsDiv[0]“>
First div
</div>
<div v-show=”showDetailsDiv[1]“>
Second div
</div>
<div v-show=”showDetailsDiv[2]“>
Third div
</div>

When I click the button, I see that the corresponding element of showDetailsDiv is changing to true, however, the corresponding division does not display. Is there anything wrong in my logic?

When I try to control the display of division using direct properties (e.g. showDiv0, showDiv1, showDiv2 & showDiv3) with the following code, it works.

showDiv: function(divNumber)
{
this.showDetailsDiv.forEach(function(item, index, array) {
array[index]=null;
});
this.showDetailsDiv[divNumber] = true;
console.log(this.showDetailsDiv);

this.showDiv0= false;
this.showDiv1= false;
this.showDiv2= false;
this.showDiv3= false;
let elementID = ‘showDiv’ + divNumber;
this[elementID] = true;
}

<div v-show=”showDiv0”>
First div
</div>
<div v-show=”showDiv1”>
Second div
</div>
<div v-show=”showDiv2”>
Third div
</div>

Any suggestions?

Solution :

Keep it simple. Template should look like:

<div v-show=”visible == 0”>
First div
</div>
<div v-show=”visible == 1”>
Second div
</div>
<div v-show=”visible == 2”>
Third div
</div>

data() {
return {
visible: null,
}
}

You can simplify showDiv method to:

showDiv: function(divNumber) {
this.visible = divNumber;
}

You can also add method isVisible to check which div is visible:

isVisible(divNumber) {
return this.visible == divNumber;
}

and use it like:

<div v-show=”isVisible(0)”>
First div
</div>

Solution 2:

If you change an array element directly, vue.js won’t be able to detect the changes due to JavaScript limitations. You should be able to do it using the corresponding array method:

this.showDetailsDiv.splice(divNumber, 1, true);

You can find more ways of doing it here: https://vuejs.org/v2/guide/list.html#Mutation-Methods

Also, if showDetailsDiv is a prop, you should probably avoid modifying it and create a copy in the component data instead.