How to call function from watch? - vue.js

data: function () {
return {
questions: []
}
},
watch: {
questions : function(val, oldVal) {
foo()
}
},
methods: {
foo() {
console.log("foo called");
}
}
Produce error: ReferenceError: foo is not defined
Also I am looking at examples: http://vuejs-ru.github.io/vuejs.org/api/options.html#watch
What this string do?
handler: function (val, oldVal) { /* ... */ },
handler it's keyword? Or it can be function?

If you want to use watch to observe your property, you could call your method it with this.foo:
data: function () {
return {
questions: []
}
},
watch: {
questions: {
handler: function(val, oldVal) {
this.foo(); // call it in the context of your component object
},
deep: true
}
},
methods: {
foo() {
console.log("foo called");
}
}
To answer your question about handler: It is a keyword property that can take either a function expression (as in the example) or a reference to a function, such as:
function myHandler() { ... } // Defined somewhere outside of the vue component object
...
handler: myHandler,
...
Just out of curiosity: Do you need to watch a property in order to do something every time it changes or could computed properties solve your problem as well?

Just to add to the answer from #nils
handler: 'foo'
also works if the function foo is within methods.
Bit shorter than
handler() {
this.foo()
}

Related

can't access "this" inside of component watcher nuxtjs

I have a component with a state property called "volume" which is bound to a slider element. I have a watcher bound to the volume property such that when the volume is updated, a function should fire
data () {return {
volume: 0,
}},
methods: {
testMethod () {
console.log("this is firing")
}
},
watch: {
volume: (v) => {
console.log("volume has been updated", v);
this.testMethod();
}
}
On running this code, the console shows the error "Cannot read property of "testMethod" of undefined
I have tried other things like accessing the $store (which was my initial issue), and that is failing to resolve too.
You can't use the fat-arrow notation within a Vue.js component (Nuxt or otherwise). The fat-arrow function definition uses the wrong context (this in your case), which is why you are running into this problem.
<script>
export default {
data () {return {
volume: 0,
}},
methods: {
testMethod () {
console.log("this is firing")
}
},
watch: {
// Your old code.
// volume: (v) => {
// console.log("volume has been updated", v);
// this.testMethod();
// }
// The corrected way.
volume(v) {
console.log("volume has been updated", v);
this.testMethod();
}
}
};
</script>
You are using an Arrow Function, which binds the this keyword to the object that defines the function, rather than the object that called the function (which is the current instance of the component in this case).
Use regular function syntax instead:
watch: {
volume(v) {
console.log("volume has been updated", v);
this.testMethod();
}
}

New property to "export default"

Is it possible or recommended to add a custom property to a component like in the below example? In that case how can I call this property from a method?
export default {
data() {
return {
test = ""
};
},
methods: {
someMethod() {
//
},
},
customLoggingData {
title : "main",
}
};
I have seen some plugins that have their own property like the customLoggingData and I was just curious to know if that was possible.
If not I'll just have it as a method.
The recommendation from the vuejs team is this:
{
data: ...,
created: function () {
this.customLoggingData = {
...
}
}
}
See this github thread for more info.

How to access nested functions in Vue.js?

Say, we have a Vue.js component built this way:
export default {
watch: {
// vars
}
},
methods: {
functionOne: function() {
function nestedFuncOne(p, q) {
// doing something
}
},
functionTwo: function() {
function nestedFuncTwo(r, s) {
// doing something
}
nestedFuncOne(param1, param2); // how to call it?
}
},
(...)
How should an inner function from the first method be called from inside of second method? this seems not to give desired output here.

Is it possible to exchange the render functions of VueJS-Components during runtime?

I've played around with vue-i18n and Vue.compile() and found a very static solution to my problem. While searching for a solution I've tried to dynamically set the render functions during runtime. Unfortunately without any success.
Out of curiosity: Is it possible to exchange the render functions of Components during runtime?
I try to do something like this:
{
props: {
toCompile: {
type: String,
required: true
},
callbackFn: {
type: Function,
default: () => {}
}
},
created (){
let res = Vue.compile(this.toCompile);
this.render = res.render;
this.staticRenderFns = res.staticRenderFns;
}
}
The following approach is working for me:
{
...
methods: {
render: function () {
var createElement = this.$createElement;
return (this._self._c || createElement)("div", {
staticClass: "element"
});
}
},
beforeCreate: function() {
this.$vnode.componentOptions.Ctor.options.render = this.$vnode.componentOptions.Ctor.options.methods.render.bind(this);
}
}
If your want slots as well, use the following render method:
render: function () {
var that = this,
createElement = (this._self._c || this.$createElement),
children = Object.keys(that.$slots).map(function(slot) {
return createElement('template', { slot }, that.$slots[slot]);
});
return createElement('div', [
createElement('component-element, {
attrs: that.$attrs,
on: that.$listeners,
scopedSlots: that.$scopedSlots,
}, children)
]);
}

Access object's fields from callback functions

I recently start learning developing metro apps using js and I faced problem updating _title and _errorMessage fields in callback functions _success and _error. When these functions are called this no more refer to MyClass object. So my question is how can update these two fields from callback functions.
(function () {
var MyClass = WinJS.Class.define(
function () {},
{
_title: "",
_errorMessage: "",
Authorize: function () {
WinJS.xhr({url:"http://example.com"})
.then(this._success,this._error);
},
_success: function(data){
this._title = data.responseData;
},
_error: function (data) {
this._errorMessage = data.responseData;
}
},
{
}
);
WinJS.Namespace.define("MynameSpace",
{
MyClass: MyClass
});
})();
One thing you can do is use the bind method of functions to set the context.
(function () {
var MyClass = WinJS.Class.define(
function () {},
{
_title: "",
_errorMessage: "",
Authorize: function () {
WinJS.xhr({url:"http://example.com"})
.then(this._success,this._error);
},
_success: (function(data){
this._title = data.responseData;
}).bind(this),
_error: (function (data) {
this._errorMessage = data.responseData;
}).bind(this)
},
{
}
);
WinJS.Namespace.define("MynameSpace",
{
MyClass: MyClass
});
})();
I don't understand how those functions could get called in the wrong context though.
Never mind, I see.
You can use a proxy variable as shown below
Authorize: function () {
var _this = this;
WinJS.xhr({url:"http://example.com"}).
then(function(data){
_this._success(data);
}, function(data){
_this._error(data);
});
}