Update data property / object in vue.js - javascript

is there a way I can programmatically update the data object / property in vue.js? For example, when my component loads, my data object is:
data: function () {
return {
cars: true,
}
}
And after an event is triggered, I want the data object to look like:
data: function () {
return {
cars: true,
planes: true
}
}
I tried:
<script>
module.exports = {
data: function () {
return {
cars: true
}
},
methods: {
click_me: function () {
this.set(this.planes, true);
}
},
props: []
}
</script>
But this gives me the error this.set is not a function. Can someone help?
Thanks in advance!

Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object, So you may create an object and add a new property like that:
data: function () {
return {
someObject:{
cars: true,
}
}
and add the property with the vm.$set method:
methods: {
click_me: function () {
this.$set(this.someObject, 'planes', true)
}
}
for vue 1.x use Vue.set(this.someObject, 'planes', true)
reactivity

Related

cant access data return{} varibles in VueJS

function HeaderreRender() {
HeaderRender = false;
this.$nextTick(() => {
HeaderRender = true;
});
};
export default {
name: 'Home',
components: {
HeaderItem,
},
data: function() {
return {
HeaderRender: true,
};
}
}
this is the code now I want to use v-if="HeaderRender" to re-render the headerItem
but when I call function HeaderreRender()
it is replying to me
Uncaught ReferenceError: HeaderRender is not defined
on the function
any suggestions? on why this happens?
Try to place the HeadereRender() function within the methods object of the component and also, it's this.HeaderRender=true
In simple terms, this method does not know about the HeaderRender variable, thus it is not defined in the scope of the function, written that way

I failed to call component's method inside of vue-froala-wysiwyg event

in laravel 8/2.6/bootstrap 4.6/Axios app using vue-froala-wysiwyg I need to get content of entered text and
call component's method with entered text.
I define event as I read here https://github.com/froala/vue-froala-wysiwyg :
import VueFroala from 'vue-froala-wysiwyg' // https://froala.com/wysiwyg-editor/docs
Vue.use(VueFroala) // https://github.com/froala/vue-froala-wysiwyg
Vue.config.productionTip = false
// let self = this
export default {
name: "RoomChat",
components: {},
data() {
return {
currentRoom: null,
...
froalaEditorConfig: {
events: {
initialized: function () {
console.log('froalaEditorConfig initialized')
},
'contentChanged': function () { // https://froala.com/wysiwyg-editor/docs/events/
console.log('froalaEditorConfig contentChanged this::')
// this - is reference to froala component
console.log(this);
console.log('this.el::')
// I tryied to get ref to root component in several ways
console.log(this.el) // undefined
console.log('this.el.$parent::')
console.log(this.el.$parent) // undefined
console.log('this.$parent::')
console.log(this.$parent) // undefined
console.log('froalaEditorConfig contentChanged this.html.get()::')
console.log(this.html.get());
parent.actionUser(this.html.get()) // I got parent.actionUser is not a function error
},
},
},
...
methods: {
actionUser(enteredText) {
...
Which way is valid?
ADDED :
Searching for decision I found
https://medium.com/dataseries/vue-js-components-parent-child-and-root-f1fcbe422feb
article with this.$root described but making inside of my event :
console.log('this.$root::')
console.log(this.$root)
Undefined is outputted.
What I see inside of event outputting this : https://prnt.sc/1r6pp4y and https://prnt.sc/1r6ptoh
Thanks!
I found decision with sending vueComponent instance as parameter :
data:(vm) => ({
...
froalaEditorConfig: {
events: {
initialized: function () {
},
contentChanged () {
vm.actionUser(this.html.get()) // That works ok
},
},
....
},
}), // data(vm) => ({

"this" doesn't work in click event handler

I have attached a click event handler to my ChartJS-derived component, like this:
export default {
extends: HorizontalBar,
data() {
return {
my_data: [],
options: {
onClick: function(event, args) {
//need to access my_data here
}
},
};
},
}
I need to access one of my data members inside the handler. Unfortunately, this.my_data doesn't work here. ChartJS documentation tells me that this event is called in the context of the Chart component, not my Vue component. How can I get access to my_data?
update
So I'm now using #Dan's way of defining the handler:
export default {
extends: HorizontalBar,
data() {
return {
my_data: [],
options: {
onClick: this.ClickHandler,
},
};
},
methods: {
ClickHandler: function(event, args) {
var datapoint = this.getElementAtEvent(event);
var value = this.my_data[datapoint._datasetIndex];
},
}
}
The handler is called correctly, but this is now refering to my Vue component and therefore I do not have any reference to the Chart context to call its getElementAtEvent.
So if I declare it in front of onClick above, I get the Chart context in this, but no longer have access to my_data. If I use your way, I get this.my_data, but lose Chart context.
You need to put the handler into your methods object and then reference it from the chart options handler:
data() {
return {
my_data: [],
options: {
onClick: this.ClickHandler,
}
};
},
methods: {
ClickHandler: function(event, points) {
// Here is how to access the chart
const c = this._data._chart;
const datapoint = c.getElementAtEvent(event)[0];
const indexBar = datapoint._index;
const indexSegment = datapoint._datasetIndex;
// Do whatever with this.my_data, indexBar, and indexSegment
}
}
The chart is accessible to the component through this._data._chart.
Create a closure variable
data() {
const vm = this;
return {
my_data: [],
options: {
onClick: function(event, args) {
this.chartjs.something;
vm.my_data[]
}
}
}

How to fire an event on Vue switch change

I have a Vue component that has a vue-switch element. When the component is loaded, the switch has to be set to ON or OFF depending on the data. This is currently happening within the 'mounted()' method. Then, when the switch is toggled, it needs to make an API call that will tell the database the new state. This is currently happening in the 'watch' method.
The problem is that because I am 'watching' the switch, the API call runs when the data gets set on mount. So if it's set to ON and you navigate to the component, the mounted() method sets the switch to ON but it ALSO calls the toggle API method which turns it off. Therefore the view says it's on but the data says it's off.
I have tried to change the API event so that it happens on a click method, but this doesn't work as it doesn't recognize a click and the function never runs.
How do I make it so that the API call is only made when the switch is clicked?
HTML
<switcher size="lg" color="green" open-name="ON" close-name="OFF" v-model="toggle"></switcher>
VUE
data: function() {
return {
toggle: false,
noAvailalableMonitoring: false
}
},
computed: {
report() { return this.$store.getters.currentReport },
isBeingMonitored() { return this.$store.getters.isBeingMonitored },
availableMonitoring() { return this.$store.getters.checkAvailableMonitoring }
},
mounted() {
this.toggle = this.isBeingMonitored;
},
watch: {
toggle: function() {
if(this.availableMonitoring) {
let dto = {
reportToken: this.report.reportToken,
version: this.report.version
}
this.$store.dispatch('TOGGLE_MONITORING', dto).then(response => {
}, error => {
console.log("Failed.")
})
} else {
this.toggle = false;
this.noAvailalableMonitoring = true;
}
}
}
I would recommend using a 2-way computed property for your model (Vue 2).
Attempted to update code here, but obvs not tested without your Vuex setup.
For reference, please see Two-Way Computed Property
data: function(){
return {
noAvailableMonitoring: false
}
},
computed: {
report() { return this.$store.getters.currentReport },
isBeingMonitored() { return this.$store.getters.isBeingMonitored },
availableMonitoring() { return this.$store.getters.checkAvailableMonitoring },
toggle: {
get() {
return this.$store.getters.getToggle;
},
set() {
if(this.availableMonitoring) {
let dto = {
reportToken: this.report.reportToken,
version: this.report.version
}
this.$store.dispatch('TOGGLE_MONITORING', dto).then(response => {
}, error => {
console.log("Failed.")
});
} else {
this.$store.commit('setToggle', false);
this.noAvailableMonitoring = true;
}
}
}
}
Instead of having a watch, create a new computed named clickToggle. Its get function returns toggle, its set function does what you're doing in your watch (as well as, ultimately, setting toggle). Your mounted can adjust toggle with impunity. Only changes to clickToggle will do the other stuff.

can't access data variables in watch handler vuejs

I'm trying to set a data variable in a watch handler function for an input field in a VueJs Component. I have something like this:
data() {
return {
params: {
// default params to 1 month
from: new Date().setMonth(new Date().getMonth() - 1),
to: Date.now(),
skip: 0,
limit: 100
}
}
}
watch: {
dates: {
handler: date => {
console.log(this.params)
if (date.start) {
this.params.from = moment(date.start, "YYYY/MM/DD")
}
if (date.end) {
this.params.to = moment(date.end, "YYYY/MM/DD")
}
},
deep: true
}
}
When I set an input for the dates variable in the view template, I get an undefined for this.params in the console log, and I get an error for trying to set this.params.from. So I tried accessing it using a method:
methods: {
printParams() {
console.log(this.params)
}
}
calling it in the view template, it correctly resolves the params object.
Am I missing something here?
To avoid additional binding, just avoid using the arrow function syntax here.Instead go with ES6 Object shorthands:
watch: {
dates: {
handler(date) {
console.log(this.params)
if (date.start) {
this.params.from = moment(date.start, "YYYY/MM/DD")
}
if (date.end) {
this.params.to = moment(date.end, "YYYY/MM/DD")
}
},
deep: true
}
}
Now this will be bound to the correct context by default.
Let's try bind this to your handler
handler(date) {
console.log(this.params)
if (date.start) {
this.params.from = moment(date.start, "YYYY/MM/DD")
}
if (date.end) {
this.params.to = moment(date.end, "YYYY/MM/DD")
}
}.bind(this)

Categories