VueJS method does not execute after I reload page, it executes after I save VS Code change [HELP?] - vue.js

After I reload the page I can't get console.log inside of the method, which means it is not getting executed, but after I make change in VSC and save it, the method executes.
I would like to add note that I have show/hide modal for the form where I try to pre-fill the values, does that makes problem? I tried removing the toggle and the result was the same.
Pls see screenshots
Some code below:
created() {
this.loadStationList();
this.loadStationGroups();
this.loadAllButtons();
this.loadAllQuidos();
this.pushButtonIds(); <---- I Try to execute this method on created but it gets executed after VS code change
},
pushButtonIds() {
for (const buttonId in this.filteredButtonList) {
this.stationButtons.push({
buttonId: this.filteredButtonList[buttonId].buttonListId,
quidoId: null,
input: null,
});
console.log(this.stationButtons);
console.log("Hello from component after saving change in VSC");
}
},
I tried to add the method to execute on beforeCreated but no success.

Just from the name, without knowing exactly, where filteredButtonList comes from, it looks to me that you call this function too early. Accessing DOM elements should take place when everything is actually in the DOM. Try moving the call into beforeMount() or even mounted(). https://vuejs.org/guide/essentials/lifecycle.html

Related

vue-router : why watch on $route trigger when previous queries rewrite with same values

i have a button in my project when i click on it two queries added to URL
onClickBtn(){
this.$router.push({queries: {name:'kevin' , age:21} })
}
and I have a watch on $route
watch:{
$route:function(){
// call API
}
}
and when i click on that button severall time
watch calls my API every time although nothing has changed
and this make a problem form me
because nothing has changed in route But API is called and the same data is
received .
what should I do to avoid calling API in watch , when queries don't changed ??
The object you are pushing on the router is always different, that's why the $route watch is launched.
You can compare the data you receive in the watch, so that when they are different then you invoke the API:
watch:{
'$route' (newRoute, lastRoute){
// Check if query is different
// call API
}
}
On top of the answer that Cristian provided, you could also even double-check if your stuff has changed before even pushing a new object to your router.
Like this
checkIfUpdateNeeded && this.$router.push({queries: {name: 'kevin', age:21 } })
That way, you will have less moving parts and you won't have a trigger in the watcher for "nothing", especially if you're pushing a bigger object and want to make a deep-diff between 2 objects.

How to determine what causes components to rerender

I am having an issue where when I change a component in my app, many unrelated components seem to be rerendering too. When I use the Vue performance timings config, I see something like (all in the span of about 200ms)
I am trying to figure out what causes these components to rerender. I saw a tip about how to tell the cause of a rerender, but when I put this snippet* in all the rerendering components, I don’t get anything logged to the console.
So, how can I find what is causing all these components to rerender?
*The code I actually put looks like
public mounted() {
let oldData = JSON.parse(JSON.stringify(this.$data));
this.$watch(() => this.$data, (newData) => {
console.log(diff(oldData, newData));
oldData = JSON.parse(JSON.stringify(newData));
}, {
deep: true,
});
}
Using the F12 dev tools in Chrome, you can track down what is triggering your component to re-render. Add an updated hook to your component as below:
updated() {
if (!this.updateCnt)
this.updateCnt = 1;
if (this.updateCnt > 1) { // set to desired
debugger;
}
console.log(`Updated ${this.updateCnt++} times`);
}
}
Refresh your page in Chrome with F12 tools open and wait for breakpoint to be hit. In the Sources tab, you will see the call stack on the right, with your updated() function as the current stack frame. Look back up the call stack and eventually you should see the code that caused the update to trigger. In my case, it was reactiveSetter() in the vue runtime, which was triggered by me setting a property in a parent component.
The code you have above will only trigger if a component's own state changes, not a parent.

Vuejs not working with dynamic array, works perfectly with static array

When I have
data: {
pictures: [
'http://lorempixel.com/1920/1920?0',
'http://lorempixel.com/1920/1920?1',
'http://lorempixel.com/1920/1920?2',
'http://lorempixel.com/1920/1920?3',
'http://lorempixel.com/1920/1920?4',
'http://lorempixel.com/1920/1920?5',
'http://lorempixel.com/1920/1920?6',
'http://lorempixel.com/1920/1920?7',
'http://lorempixel.com/1920/1920?8',
'http://lorempixel.com/1920/1920?9',
]
}
it renders perfectly, but when I fetch the data and get it like this in the console and perfect data in the vue dev tools
["https://picsum.photos/id/1020/4288/2848",
"https://picsum.photos/id/1021/2048/1206",
"https://picsum.photos/id/1022/6000/3376",
"https://picsum.photos/id/1023/3955/2094",
"https://picsum.photos/id/1024/1920/1280",
__ob__: Observer]
it populates the dom but not rendered.
what am I missing??
If I face that situation then I check if I have created that property as reactive.
Means I have added v-model on it or not.
Other way is to add it in watch propery as shown below
watch:{
//just write name of the data propery and make it function
picutres(){}
//that's it
}
Now it will listen for the changes.
If you still somehow cannot fix that problem then other solution it to use custom events or a function
You will call function or trigger an event whenever you change your pictures array.
Then in function or event you can update your pictures array

Trying to get vue.js to render something conditionally based on a method in created()

I have a call in my created method which has an await.
I want to know that the results of that call are loaded so that i can conditionally show/hide things in the DOM.
Right now it looks like the DOM is being rendered before that method has completed. But I though that methods in created were called before the DOM rendered?
You're correct in assuming that the created hook runs before the component mounts. However, the lifecycle hooks are not waiting for async calls to complete. If you want to wait for that call to be completed and data to load, you can do so by using a Boolean that you set to true when your data has loaded.
Your template:
<div v-if='dataLoaded'>Now you can see me.</div>
in your vue instace
export default {
data () {
return {
dataLoaded: false
}
},
created () {
loadMyData().then(data => {
// do awesome things with data
this.dataLoaded = true
})
}
}
This way you can keep your content hidden until that call has resolved. Take care with the context when you handle the ajax response. You will want to keep this as a reference to the original vue instance, so that you can set your data correctly. Arrow functions work well for that.

Vuetify and require.js: How do I show a dynamic component?

I am creating a tab component that loads its v-tab-item components dynamically, given an array of configuration objects that consist of tabName, id, and tabContent which is a resource location for the component. I have it successfully loading the components. However, they don't actually initialize (or run their created() methods) until I switch tabs. I just get empty tabs with the correct labels. Using the DOM inspector initially shows just <componentId></componentId>, and then when I switch tabs, those tags are replaced with all of the component's content.
How do I get the dynamic components to initialize as soon as they are loaded?
EDIT: I created a CodePen here:
https://codepen.io/sgarfio/project/editor/DKgQON
But as this is my first CodePen, I haven't yet figured out how to reference other files in the project (i.e. what to set tabContent to so that require.js can load them up). I'm seeing "Access is denied" in the console, which makes it sound like it found the files but isn't allowed to access them, which is weird because all the files belong to the same project. So my CodePen doesn't even work as well as my actual project. But maybe it will help someone understand what I'm trying to do.
Also, after poking around a bit more, I found this:
http://michaelnthiessen.com/force-re-render/
that says I should change the key on the component and that will force the component to re-render. I also found this:
https://v2.vuejs.org/v2/guide/components-dynamic-async.html
Which has a pretty good example of what I'm trying to do, but it doesn't force the async component to initialize in the first place. That's what I need the async components to do - they don't initialize until I switch tabs. In fact they don't even show up in the network calls. Vue is simply generating a placeholder for them.
I got it working! What I ended up doing was to emit an event from the code that loads the async components to indicate that that component was loaded. The listener for that event keeps a count of how many components have been loaded (it already knows how many there should be), and as soon as it receives the right number of these events, it changes the value of this.active (v-model value for the v-tabs component, which indicates which tab is currently active) to "0". I tried this because as I noted before, the async components were loading/rendering whenever I switched tabs. I also have prev/next buttons to set this.active, and today I noticed that if I used the "next" button instead of clicking on a tab, it would load the async components but not advance the tab. I had already figured out how to emit an event from the loading code, so all I had to do at that point was capture the number of loaded components and then manipulate this.active.
I might try to update my CodePen to reflect this, and if I do I'll come back and comment accordingly. For now, here's a sample of what I ended up with. I'm still adding things to make it more robust (e.g. in case the configuration object contains a non-existent component URL), but this is the basic gist of it.
created: function() {
this.$on("componentLoaded", () => {
this.numTabsInitialized++;
if(this.numTabsInitialized == this.numTabs) {
// All tabs loaded; update active to force them to load
this.active = "0";
}
})
},
methods: {
loadComponent: function(config) {
var id = config.id;
var compPath = config.tabContent;
var self = this;
require([compPath], function(comp) {
Vue.component(id, comp);
self.$emit("componentLoaded");
});
}
}