Vue creating a plugin - javascript

I feel a bit like I'm missing something very simple, but I've been trying different stuff out and searching all over the place and can't figure out how to use a method from a custom plugin in my Vue application.
In 'vuePlugin.js' I have something like:
const myPlugin = {};
myPlugin.install = function(Vue, options){
Vue.myMethod = function(){
console.log("It worked!");
}
}
In my main.js I have:
import myPlugin from './js/vuePlugin.js'
Vue.use(myPlugin);
Then in my App.vue I have:
export default {
name: 'app',
props: {},
data () {
return{ someData: 'data' }
},
beforeCreate: function(){
myMethod();
}
}
With this I get an error that "myMethod is not defined".
I've tried saying:
var foo = myPlugin();
console.log(foo);
In my console I get an object called "install" with arguments:
"Exception: TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context. at Function.remoteFunction"
All of the documentation seems to just show how to create the plugin and "use" it, but not actually how to access anything in it. What am I missing here?

You have to export your object to be used in vuejs as follows
file vuePlugin.js
const myPlugin = {}
myPlugin.install = function (Vue, options) {
Vue.myMethod = function () {
console.log('It worked!')
}
Vue.prototype.mySecondMethod = function () {
console.log('My second Method ')
}
}
export default myPlugin
while calling the method you cannot call the method directly, you have to use as following code shown
file App.vue
export default {
name: 'app',
props: {},
data () {
return{ someData: 'data' }
},
beforeCreate: function(){
Vue.myMethod(); // call from Vue object , do not directly call myMethod()
this.mySecondMethod() // if you used prototype based method creation in your plugin
}
}
hopes it will help you

Related

Why property of the function invisible when function imported to another file?

I have this function in file colled dataservice.js:
export function DataServices() {
var that = this;
that.dataServiceUrl = "/CrossServices/SearchService.svc";
var ds = {
getStreets: getStreets
};
return ds;
function getStreets(expr, callback, error) {
//some logic
return result;
}
}
I import function above in mapApp.js file like this:
import { DataServices from "/src/js/services/dataservices";
And try to access getStreets property this way:
DataServices.getStreets(3, null, null);
But I get this error on the row above:
error: Cannot read property 'getStreets' of undefined
Any idea why getStreets property not visible?
You are exporting a named function DataServices
You need to make it the default export, or import it by name:
export default function DataServices
or
import { DataServices } from "/src/js/services/dataservices";

How to use Vue plugin in Store?

Is there a proper / documented way of using a plugin inside vuex module or plain js module?
I am using event bus to acheive it, not sure if it is the correct / best way. Please help.
Plugin1.plugin.js:
const Plugin1 = {
install(Vue, options) {
Vue.mixin({
methods: {
plugin1method(key, placeholderValues = []) {
return key;
},
},
});
},
};
export default Plugin1;
In App.vue:
Vue.use(Plugin1, { messages: this.plugin1data });
In store / plain-js module:
const vue = new Vue();
const plugin1method = vue.plugin1method;
you can access your Vue instance using this._vm;
and the Vue global using import Vue from 'vue'; and then Vue;
I'm guessing you defined an instance method, so it would be the former (this._vm.plugin1method())
update
I can't tell you which way you should use it because it I can't see how your function is defined in your plugin.
However, here is an example that should illustrate the difference between instance and global
const myPlugin = {
install: function(Vue, options) {
// 1. add global method or property
Vue.myGlobalMethod = function() {
// something logic ...
console.log("run myGlobalMethod");
};
Vue.mixin({
methods: {
plugin1method(key, placeholderValues = []) {
console.log("run mixin method");
return key;
}
}
});
// 4. add an instance method
Vue.prototype.$myMethod = function(methodOptions) {
console.log("run MyMethod");
// something logic ...
};
}
};
Vue.use(Vuex);
Vue.use(myPlugin);
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
this._vm.$myMethod();
Vue.myGlobalMethod();
this._vm.$options.methods.plugin1method(); // <-- plugin mixin custom method
state.count++;
}
}
});
when you commit the increment ie: this.$store.commit('increment') both methods will execute

How to solve Uncaught TypeError: this.filters is not a function ? (vue.js 2)

My component code is like this :
<script>
import _ from 'lodash'
export default{
props:['search','category'],
data(){
return{
price_min:'',
price_max:''
}
},
computed:{
filters(data){
const price = {min:this.price_min, max:this.price_max}
return {q:this.search, category:this.category, sort:data, location:data, price}
},
},
methods:{
filterProduct: _.debounce(function(data=null){
this.$store.dispatch('getProducts', this.filters(data))
},500)
}
}
</script>
My full code is like this : http://pastebin.com/K7vwU0yY
When executed, on the console exist error like this :
Uncaught TypeError: this.filters is not a function
How can I solve the error?
computed:{
filters(data) { // the first argument is supposed to be the `this`
const price = {min:this.price_min, max:this.price_max}
return {q:this.search, category:this.category, sort:data, location:data, price}
},
},
methods:{
filterProduct (data = null) {
return _.debounce(function (data=null) => {
this.$store.dispatch('getProducts', this.filters(data))
},500).call(this, data)
}
}
You have lost context to the vue component instance by using an anonymous function. Use an arrow function or save the context in a let self = this
In your case, you are returning a function by using _.debounce(fn() {}, ms) but doing so, you lost the context to this.
So I moved your debounce code inside a method which .calls the function callback returned by debounce with this set to vue component instance.
Moreover computed properties are not to be used as function. this.filters(data) therefore will still give the similar error as it is a property, just like the ones you can create in data of your vue component instance. Use a method instead.

Calling a function recursively in the context of "export default"?

This may be obvious to others but I don't know the syntax for calling a function recursively in the following code:
//request.js
export default {
send() {
... do stuff ...
this.send(); // Can't call "send" of undefined
}
}
//main.js
import request from './request'
export default class Main extends Component {
init() {
request.send();
}
}
In the above example, I'm calling the send function from main.js. All this is working fine but I have a condition in the send function that will recall the same function. The problem is that I have no idea how to call the function from within the function. Anybody?
If you want to call the default export recursively in Node.js, using Babel.js to transpile, you can use the exports object:
// request.js
export default {
send() {
console.log('Yo');
setTimeout(() => {
exports.default.send();
}, 1000);
},
};
Importing:
// main.js
import request from './request';
request.send(); // Writes "Yo" to the console once per second
This is because Babel.js simply transforms to the CommonJS syntax. This:
export default 42;
Becomes this:
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = 42;
No idea how this may change in a future implementation of ES6 Modules in Node.js.
I don't see any reason why this.send() wouldn't work, given you are exporting an object with a method.
But if it doesn't work, you can always use a named function expression:
export default {
send: function send() {
… send() …
}
};
or a named function declaration:
function send() {
… send() …
}
export default { send };
or just name your exported object:
export default const request = {
send() {
… request.send() …
}
};
But I would recommend to not default-export an object at all, and use named exports instead so that you can import them separately or on a namespace object:
// request.js
export default function send() {
… send() …
}
// main.js
import * as request from './request'
…
request.send()
well just as a quick glimpse, I would say that you should
console.log(this)
to see the value of it in the first and second request.
I didn't build your code to check it, but I assume it is an issue with your context.
Still not sure what you try to achieve, but you can always use
someFunction.bind(this)
again it is quite vague but maybe it will give you an idea.
i think this is simple solution.
//request.js
export function send () {
... do stuff ...
send(); // Can't call "send" of undefined
}
//main.js
import {send} from './request'
export default class Main extends Component {
init() {
send();
}
}

EmberJS - Call super action after promise resolves

I am using Ember 2.6.0
I am extending a third party component that has some functionality defined in a action and I want to catch that action in my subclass, call a function that returns a promise and fire the supers action when the promise resolves.
So the third party component does this:
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
theAction() {
this._somePrivateFunction();
//do other stuff
}
}
});
And in my subclass I am doing:
import Ember from 'ember';
import ThirdPartyComponent from 'path/to/component'
export default ThirdPartyComponent.extend({
_funcThatReturnsPromise() {
return new Ember.RSVP.Promise();
}
actions: {
theAction() {
const thePromise = this._funcThatReturnsPromise();
thePromise.then(() => {
// undefined!
this._super(...arguments);
})
}
}
});
this._super() does not resolve to the parent component action when called in the promises callback. I've tried storing the supers function as a property and calling it:
theAction() {
const thePromise = this._funcThatReturnsPromise();
this.set('superFunc', this._super);
thePromise.then(() => {
// calls the super but "this" inside the supers action is undefined
this._super(...arguments);
})
}
This, in addition to being ugly, results in this inside the supers action to be undefined. I'm not sure why that is.. looking through some docs.
There is also the option of calling send() in my subclasses action:
theAction() {
const thePromise = this._funcThatReturnsPromise();
this.set('superFunc', this._super);
thePromise.then(() => {
//infinite loop!
this.send('theAction');
});
}
But this of course results in an infinite loop since the function ends up calling itself.
I'm not sure how to proceed here. Could anyone tell me if there is a clean way to do what I am trying to do here? Any advice would be appreciated. Thanks much!
In child component do like :
theAction() {
const thePromise = this._funcThatReturnsPromise();
let parentAction = this._super;
let self = this;
thePromise.then(() => {
//parent usage
parentAction();
// this usage
self.doSome();
});
}

Categories