Vuejs not working with dynamic array, works perfectly with static array - vue.js

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

Related

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

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

Weird Vuejs props behavior with arrays

I created a form component where i pass an object prop to it containing strings and an object array. I then i transfer the elements of the props to the component variables so i can edit them without interacting with the props directly like so:
beforeMount(){
this.var1 = this.props.var1
this.var2 = this.props.var2
this.array = this.props.array
}
when i edit all the other variables, close my component and open it again everything resets BESIDES the array. every time i try to interact with it the reset never happens. i know i am not interreacting directly with the props either in any part of my code so i don't really why this happens when when everything works fine. To fix that i had to do the following:
beforeMount(){
this.var1 = this.props.var1
this.var2 = this.props.var2
this.props.array.forEach(element => {
this.array.push(element)
})
}
why does this work exactly?
I have also been having similar problems with method specific variables not resetting after the function is already over so i find these behaviors a little weird. I am also using "v-if" and also tried to use component keys to reset the component but it doesn't work for the array for whatever reason.
try to copy your array like that :
this.array = [...this.props.array]
I'm not sure about it, but as you pass it within an object, you might actually use you array as reference and not values as you 'd like to.

Vue Chart JS and options reactivity

I'm trying to recreate the doughnut to pie change in behavior as seen here:
https://www.chartjs.org/samples/latest/scriptable/pie.html
I'm using VueJS version of Chart JS and after recreating this it seems to not be reactive at all.
Here is the method that I use to change the chart to the other one:
togglePieDoughnut() {
this.options.cutoutPercentage = 50;
}
As you can see it does not work as intended, even tough I used reactiveprop mixin.
EDIT: To be precise I want to recreate the chart update behaviour as seen in the example on chartjs.org website. I do not want to rerender the chart, rather update it so the transition remains smooth.
Seems like the issue is the template isn't reacting to the data changes. Best way to force template re-render is to bind a key, for our example, we are changing this value, the template will update when its changed:
:key="options.cutoutPercentage"
Codepen example:
https://codesandbox.io/s/vue-chartjs-demo-t8vxu?file=/src/App.vue
What if we add a watch to the options variable and rerender the chart when it happens?
watch: {
options: function() {
this._chart.destroy();
this.renderChart(this.donut, this.options);
}
}
When you look at the code of Piechart.vue, it seems that it only render one time on mounted. Thats why when changing the options, it not gonna reflected in the chart because there is no function to rerender.
The only way is you have to remove the old pie chart and create a new one when options changed. There's a lot of way to do the force re-render, but still the cleanest way is as procoib said, attach a key to it.
When using object as props and update one property in it, the reactivity system will not trigger the change, because the object is the same and only one property updated. Thus, the child component will not get the updated value.
What can you do is to recreated the object with the updated property. See below code:
this.options = Object.assign({}, this.options, { cutoutPercentage: 50 });
And in the child component, use watcher re-render the chart
watch: {
options(newVal) {
}
}

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");
});
}
}

Vue components not reactive to change in array

My Vue instance has an array of Vue components:
let vm = new Vue({
el: '#maze',
data: {
tiles: []
},
The components populate the DOM properly per:
<truchet-tile v-for="tile in tiles" v-bind:key="tile.id" v-on:click="tile.rotate()">
</truchet-tile>
I initialize the array using .push().
When I inspect the array, it's all set up correctly, however the Vue components have their initial/default values, all 0: (id should be 2 here, and ttype a random number between 0 and 6)
The data (ttype) in each component remains 0. I can't figure out why it's not reacting.
JSFiddle here.
If you take a look at this JSFiddle, you'll see your code work as intended (or atleast how I understood it). The main issue was that you were creating the array of tiles with generic objects. These objects don't automatically transform to truchet-tiles with the needed properties.
What needed to be done was passing the properties to each instance of truchet-tile. Next thing what needed to be done was to move the v-on:click handler. You want the rotate method to fire when a user clicks on the truchet-tile. But since an instance of truchet-tile eventually becomes an img (because of the template attribute), we need the handler on this img instead.
If you have any more questions, feel free to ask