How to use a mixins function inside another mixins function? - javascript

How do I combine two functions in vue mixins??
Vue.mixin({
methods: {
functionOne: () => {
console.log(1)
}
functionTwo: () => {
this.functionOne()
}
},
mounted () {
this.functionTwo()
}
})
//expected: console
1
//actual: console
Cannot read property 'functionOne' of undefined

if you use ES6 arrow functions with Vue methods, it changes the context of this. If you phrase it like:
Vue.mixin({
methods: {
functionOne () {
console.log(1)
},
functionTwo: function () {
this.functionOne()
}
},
mounted () {
this.functionTwo()
}
})
it works perfectly.
(the functionOne () and functionTwo: function () syntax are both valid, which is why they both appear in the example.)

Related

VueJS error "Uncaught TypeError: this.sendDrag is not a function" in mounted ()

I can't figure out why this.sendDrag('started') returns this error:
"Uncaught TypeError: this.sendDrag is not a function"
methods: {
sendDrag (val) {
console.log(val)
}
[...]
mounted () {
this.$nextTick(() => {
this.$refs.flickity.on('dragStart', function () {
this.stageDragging = true
this.sendDrag('started')
})
What causes the error and how to fix it?
You need to capture the value of this in the closure because you are calling it from a function that has a different this.
If you used the arrow-lambda notation ()=>{} instead of function() it would capture this for you automatically. And that is the real difference between the two notations.
mounted () {
this.$nextTick(() => {
const that = this;
this.$refs.flickity.on('dragStart', function () {
that.stageDragging = true
that.sendDrag('started')
})

Calling Vue method from inside mounted function

In my Vue mounted code, I am calling a function test via this.test(). This works fine as intended.
When however I am calling this.test() from the new ResizeObserver function, I am getting an error
this.test is not a function
I understand that this is because the this there is now pointing to the resizeObserver. What I do not understand is what I should use there instead. Removing the this also gives an error.
I have the following Vue code
mounted: function() {
this.test();
new ResizeObserver(function() {
this.test();
}).observe(this.g("tC"));
},
methods: {
test: function() {}
....
}
You should either bind "this" to the function passed to ResizeObserver
mounted: function() {
this.test();
new ResizeObserver(function() {
this.test();
}.bind(this)).observe(this.g("tC"));
},
Or use an arrow function (if your environment supports ES6) since arrow functions use "this" value of the outer scope:
mounted: function() {
this.test();
new ResizeObserver(() => {
this.test();
}).observe(this.g("tC"));
},
It works for me like this
mounted: function() {
$vm = this;
new ResizeObserver(function() {
$vm.test();
}).observe(this.g("tC"));
},
methods: {
test: function() {}
....
}
Use Arrow functions to bind scope
new ResizeObserver(()=> { //--> Arrow Function
this.test();
}).observe(this.g("tC"));

Function not defined error when calling from another function

So I am calling a function from inside another function like this:
methods: {
selectStep: function (id) {
...
}
controlStep: function () {
selectStep(1);
...
}
}
but all I get is an error saying:
Uncaught ReferenceError: selectStep is not defined
Do you have any idea about what could be happening here?
Your approach is trying to execute a function from the window object or from whatever context was declared that object methods.
You need to call that function as follow:
this.selecteStep(1);
Further, you need to separate those methods/functions using comma ,
const methods = {
selectStep: function (id) {
console.log('called!', id);
},
controlStep: function () {
this.selectStep(1);
}
}
methods.controlStep();
You have to use this.anotherMethodName
<template>
...
<button #click="callMethod"></button>
...
</template>
<script>
export default {
methods: {
firstMethod() {
console.log('called')
},
callMethod() {
this.firstMethod()
}
}
}
</script>

Vuejs calling a method from $on event

Am building a vuejs component
methods: {
filterPeople: function() {
console.log('hello')
//do some good stuff
},
},
beforeCreate() {
//do some ajax stuff
},
mounted() {
Event.$on('applied', function() {
console.log('the event is being caught')
this.filterPeople();
})
})
The error I get is
this.filterPeople(); is not a function
When I move it outside the Event.$on block it does call the method.
How does this work?
It was all to do with Scope
var self = this;
Event.$on('applied', function() {
self.filterPeople();
})
Use arrow functions to save the context:
Event.$on('applied', () => this.filterPeople());

Vue.js inheritance call parent method

Is it possible to use method overriding in Vue.js?
var SomeClassA = Vue.extend({
methods: {
someFunction: function() {
// ClassA some stuff
}
}
});
var SomeClassB = SomeClassA.extend({
methods: {
someFunction: function() {
// CALL SomeClassA.someFunction
}
}
});
I want to call ClassA someFunction from ClassB someFunction. Is it even possible?
No, vue doesn't work with a direct inheritance model. You can't A.extend an component, as far as I know. It's parent-child relationships work mainly through props and events.
There are however three solutions:
1. Passing props (parent-child)
var SomeComponentA = Vue.extend({
methods: {
someFunction: function () {
// ClassA some stuff
}
}
});
var SomeComponentB = Vue.extend({
props: [ 'someFunctionParent' ],
methods: {
someFunction: function () {
// Do your stuff
this.someFunctionParent();
}
}
});
and in the template of SomeComponentA:
<some-component-b someFunctionParent="someFunction"></some-component-b>
2. Mixins
If this is common functionality that you want to use in other places, using a mixin might be more idiomatic:
var mixin = {
methods: {
someFunction: function() {
// ...
}
}
};
var SomeComponentA = Vue.extend({
mixins: [ mixin ],
methods: {
}
});
var SomeComponentB = Vue.extend({
methods: {
someFunctionExtended: function () {
// Do your stuff
this.someFunction();
}
}
});
3. Calling parent props (parent-child, ugly)
// In someComponentB's 'someFunction':
this.$parent.$options.methods.someFunction(...);
In case someone's interested in a JustWorksTM solution:
var FooComponent = {
template: '<button #click="fooMethod()" v-text="buttonLabel"></button>',
data: function () {
return {
foo: 1,
bar: 'lorem',
buttonLabel: 'Click me',
}
},
methods: {
fooMethod: function () {
alert('called from FooComponent');
},
barMethod: function () {
alert('called from FooComponent');
},
}
}
var FooComponentSpecialised = {
extends: FooComponent,
data: function () {
return {
buttonLabel: 'Specialised click me',
zar: 'ipsum',
}
},
methods: {
fooMethod: function () {
FooComponent.methods.fooMethod.call(this);
alert('called from FooComponentSpecialised');
},
}
}
jsfiddle: https://jsfiddle.net/7b3tx0aw/2/
More info:
This solution is for devs that can't use TypeScript for some reason (which I think allows defining vue components as classes, which in turn allows full inheritance feature-set).
Further elaboration about the solution (whys and hows): https://github.com/vuejs/vue/issues/2977
This ain't that ugly, considering that no rocket science is used here (calling anonymous functions with the this pointer replaced should be no magic for any decent js dev).
How to use Function.prototype.call()
Reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
Sample code:
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name);
// expected output: "cheese"
In case someone asks for a solution here is mine and works fine :
var SomeClassA = {
methods: {
someFunction: function () {
this.defaultSomeFunction();
},
// defaultSomeFunction acts like parent.someFunction() so call it in inheritance
defaultSomeFunction: function () {
// ClassA some stuff
},
},
};
var SomeClassB = {
extends: SomeClassA,
methods: {
someFunction: function () {
// Replace the wanted SomeClassA::someFunction()
this.defaultSomeFunction();
// Add custom code here
},
},
};
using juste extends from https://v2.vuejs.org/v2/api/#extends replaces the usage of Vue.extends()

Categories