Reactive Vue Data Does Not Render in Firefox Columns - firefox

I've run into an extremely strange problem while developing a Vue SPA in Firefox (v89.0.1). Reactive data will not render on the page when it is contained within columns. Here is an example:
<template>
<div style="column-count: 2">
<div style="break-inside: avoid;">
Column 1
</div>
<div style="break-inside: avoid;">
Column 2
<div v-if="test">{{ test }}</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
test: ''
};
},
mounted() {
setTimeout(() => {
this.test = 'tested';
}, 2000);
}
};
</script>
In Chrome, the word "tested" is correctly rendered in the second column. In Firefox the word "tested" does not immediately appear, but it will appear later if the window is resized. The issue is resolved if the column-count style is removed.
Is this a known issue and, if so, does anyone have a suggested work around? Really scratching my head on this. (Note: I'm using column-count to create a masonry layout, so I can't easily substitute another grid solution.)

Related

#focus event is not bubble by default

Vue version:
3.2.39
While click on the button, the focus does not bubble to the wrapper, and that is why it does not show the "wrapper focus". How to fix this?
<template>
<div tabindex="-1" #focus="onWrapperFocus" #blur="onWrapperBlur">
<button #focus="onInnerFocus" #blur="onInnerBlur">Hello</button>
</div>
</template>
<script >
export default {
setup() {
return {
onWrapperFocus() {
console.log("wrapper focus");
},
onWrapperBlur() {
console.log("wrapper blur");
},
onInnerFocus() {
console.log("inner focus");
},
onInnerBlur() {
console.log("inner blur");
},
};
},
};
</script>
Expected behavior:
inner focus
wrapper focus
There is another phase of event called "capturing". It is rarely used in real code, but can be usefull in this case.
You can add the capturing phase by adding .capture after the event name like shown below:
<div tabindex="-1" #focus.capture="onWrapperFocus" #blur.capture="onWrapperBlur">
<button #focus="onInnerFocus" #blur="onInnerBlur">Hello</button>
</div>
As it turned out, this is not related to vue. 😆 Just needs to read the documentation time to time. About focusin/focusout -
https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event
Instead focus/blur, I use focusin/focusout and it's work how I wanted.

localStorage persisting with looped Vue component

I'm having the strangest time getting localStorage to work on my local machine. I seem to be losing indexes in the array I built, I've been trying for hours to figure out why with absolutely no luck. I've even tried different ways of building the array.
Here is the component I am loading with a v-for loop. this is working as expected.
home.vue
<tweets
v-for="tweet in tweets"
v-bind:key="tweet.id"
v-bind:tweet="tweet"
></tweets>
And here is the trouble-maker component. It loads a number of tweets that can be voted on. (Feel free to ignore the HTML, I'm not sure it's relevant.)
tweets.vue
<template>
<div class="col-2 d-flex">
<div class="align-self-center ml-3">
<div class="row py-1">
<i
class="fas fa-arrow-up"
style="font-size: 30px"
v-on:click="voteUp"
></i>
</div>
<div class="row py-1">
<i class="fas fa-arrow-down" style="font-size: 30px"></i>
</div>
</div>
</div>
</template>
<script>
export default {
data: function () {
return {
localStorage: [],
};
},
props: {
tweet: Object,
},
created: function () {
this.localStorage = JSON.parse(localStorage.storageData);
console.log(this.localStorage);
},
methods: {
voteUp: function () {
axios
.get("/api/vote/2/1")
.then(({ data }) => {
var test = {
"tweet_id": 1,
"vote_status": 1
};
this.localStorage.push(test);
console.log(this.localStorage);
localStorage.setItem("storageData", JSON.stringify(this.localStorage));
console.log("go");
//persist?
})
.catch(function (error) {
alert("Take a screen shot and send this to me." + error);
console.log(error);
});
},
},
};
</script>
So if you take a look at my localStorage variable, I have it being set to the current localStorage found in the browser, however...it's having this strange problem where if I click on the button that triggers the voteUp function, it will sometimes delete some of the indexes in the array. I'm having trouble explaining so I've make a quick video to demonstrate.
https://streamable.com/kkhnrx
as you can see, I'm firing the event and the array starts growing, but as I scroll down to different buttons (remember the tweets are looped) the array will lose a few of it's indexes. I have no idea why this is happening. I assume it has something to do with the component being looped and scope problems?
This looks exactly like race condition. There are multiple component instances that compete over the storage, and it becomes overwritten eventually.
This makes an early copy that won't contain updates from other instances:
this.localStorage = JSON.parse(localStorage.storageData)
this.localStorage should be assigned immediately before updating the storage, or there should be a common state for all component instances (e.g. by using Vuex with persistence).
You have an error in your created function, right?
If you want to get "storageData" from local storage it should be:
created: function () {
this.localStorage = JSON.parse(localStorage.getItem('storageData'));
console.log(this.localStorage);
},

What is this.loading = false?

I am using Laravel and Vue.
When I was searching on the internet I saw the following code.
<template>
<div>
<h3 class="text-center">Create Movie</h3>
<div class="row">
<div class="col-md-6">
<form #submit.prevent="createMovie">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" v-model="movie.name">
</div>
<div class="form-group">
<label>Director</label>
<input type="text" class="form-control" v-model="movie.director">
</div>
<button type="submit" class="btn btn-primary">Create movie</button>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
movie: {}
}
},
methods: {
createMovie() {
this.axios
.post('http://localhost:8000/api/movie/create', this.movie)
.then(response => (
this.$router.push({name: 'movie'})
))
.catch(error => console.log(error))
.finally(() => this.loading = false)
}
}
}
I am trying to find out what the last line
.finally(() => this.loading = false)
is doing. I am searching on the internet but I can't find what it does. Also, I tried running the code without the last line however, it did not make any change.
Can someone please tell me what this is doing and when it is useful?
Without seeing the associated Vue template we cannot explain what it is doing exactly, however, we can be fairly confident that the value of loading will be used to show/hide some sort of overlay or activity spinner.
The purpose of the overlay/activity spinner is to provide visual feedback to the user that something is happening. This is useful when loading large amounts of data into your page, or when you perform a long running process (such as uploading a large file for example). So rather than the user seeing nothing on first page load, or clicking a button and wondering if it worked, they are provided with something to let them know that something is happening.
A basic example of what this might look like in the Vue template could be:
// if the value of loading is true, show this
<div v-if="this.loading">Loading, please wait ...</div>
// otherwise show this
<div v-else>Other content</div>
Your example is setting the value of loading to false once a response has been received from your axios request. You would probably want to set the value of loading to true prior to making the request to show an overlay/activity spinner.
Uncaught (in promise) ReferenceError: ture is not defined
You have a typo, it should be true not ture.

Vuetify / Mouseover does not work with v-system-nav

Is there a way to make mouseover work with v-system-nav? I have the following fiddle which demonstrates my issue:
https://jsfiddle.net/6dqfz3j2/1/
<div>
<div id="content">
<v-card #mouseover="abc">Mouseover this and look at the console. Mouseover works!</v-card>
<v-system-bar #mouseover="abc">Mouseover this and look at the console. Mouseover does not work!</v-system-bar>
</div>
</div>
...
methods: {
abc() {
console.log('hi');
},
},
Is it a bug? Is there some property I can overwrite to make it work?
Thanks!
Got it. It needs to be #mouseover.native="abc" for the v-system-nav

VueJS mouseover in for loop

I have a for that will create a component for each index.
In this component, I have a child div containing edit, add, minus buttons.
I would like it to be displayed on the component mouseover.
How do I achieve this dynamically without having to play with indexes ?
Thank you kindly.
Post component
<template>
<div v-on:mouseleave.native="showOperations = false"
v-on:mouseover.native="showOperations = true">
<!-- post data -->
<div v-if="showOperations">
<!-- operations -->
</div>
</div>
</template>
<script>
export default {
...
data () {
return {
showOperations: false
}
},
...
</script>
List of post
<post v-for="post in posts"
:key="post.id"
:post="post">
</post>
This pattern works for me and I think it works for you as well

Resources