Call a Vue method from outside the Vue app (Vue Webpack CLI) - javascript

I need to call a method from outside my app. I am using the Vue CLI. My method is in a component and looks something like this:
export default {
name: 'home',
...
methods: {
theMethodINeedToCall() {
// does stuff
}
}
I have been searching for a way to access theMethodINeedToCall(). It's not hard to get there when you're not using the Vue CLI, but with the CLI, I can't seem to find my way there.

If the method has nothing to do with the component it's better you host the method outside of the component
At last component is just an object ,just import the component where yo want and call the method;
import MyComponent from './path/'
MyComponent.methods.theMethodINeedToCall();

Related

How can I access/mutate Vue component properties from vanilla JS

I have a Vue 2 project made with Vue CLI, and I plan to distribute it as a library, ideally with the dependencies and Vue syntax stuff abstracted away by some kind of wrapper script. I would like to allow this kind of interaction:
// mount the component on a plain JS webpage
const myComponent = new MyComponent('#my-component');
// handle events from the component in vanilla JS
myComponent.on('load', someHandler);
// (A.) call a component method and get a return value
const processedData = myComponent.process(123);
// (B.) access/mutate reactive component data properties
myComponent.setMessage('Hello world!');
I have tried changing the "build target" to build a Libary or a Web Component as mentioned in the Vue documentation. I can mount the library component just fine, and handle events, but it doesn't mention how I might interact with the component data from outside the Vue VM (see comments A and B).
How can I access Vue component methods and data properties from outside the Vue VM, in vanilla JS?
To access the Vue component properties (and methods) outside of the VM, you can mount it with a "template ref" like this:
const vm = new Vue({
components: {
MyComponent,
},
template: `
<my-component
ref="myComponent"
/>
`,
}).$mount('#mount-element");
and then you can call its methods like this:
vm.$refs.myComponent.someFunction();
You'll get the returned values and it will access/mutate reactive properties inside the VM as expected.
To use the class syntax described in the original question, we can create a simple class to wrap the vue component:
// import the component built by Vue CLI with the "library" build target
// (puts `MyComponent` in the global namespace)
import './MyComponent.umd.min.js';
import Vue from 'https://unpkg.com/vue#2/dist/vue.esm.browser.min.js';
export default class {
constructor(mountElement) {
// mount vue VM with a template ref to access its properties
const thisClass = this;
this.vm = new Vue({
components: {
MyComponent,
},
template: `
<my-component
ref="myComponent"
/>
`,
}).$mount(mountElement);
this.component = this.vm.$refs.myComponent;
}
// define methods that could call this.component's functions
someFunction() {
// do stuff
return this.component.someFunction()
}
}
It seems to work pretty well. A possible improvement would be to build the component library with a different tool, since Vue CLI v3 (with Vue v2 projects) can't output ESM module files, so the best we can do is a UMD modle that gets defined globally.

Vue - make helper for root component and all child component

Please is there a way to create a helper function on a root component in vue and also make the function accessible in all child components?
You can create helper functions and use it as a plugin. In case of you are using nuxt.js, you can create helpers.js in plugins and register it in nuxt.config.js file.
import Vue from 'vue'
import helpers from './helpers'
const plugin = {
install () {
Vue.prototype.$helpers = helpers
}
}
Vue.use(plugin)
In helpers.js, you can define all helper functions.
export default {
cloneObj(val) {
return JSON.parse(JSON.stringify(val));
}
};
Then you can use it in any child components like this:
this.$helpers.cloneObj()
You need to store it in a separate file because it's frustrating to pass it as a prop from one component to another and that's the main idea of why state management like Vuex is a better solution because it provides a centralized state manage which you can access from any component

Set a class to prototype in NuxtJS Vue

How to set a class to prototype correctly in Vue NuxtJS?
I create plugin
nuxt.config.js
plugins: [
{ src: "~/plugins/global.js" },
],
global.js
import Vue from "vue";
import CustomStore from "devextreme/data/custom_store";
//try set in prototype
Vue.use(CustomStore)
have error
A class must be instantiated using the 'new'
I understand that this is not correct, but I can not find anywhere how to initialize it
Vue.use(new CustomStore());
no error but how call?
I want to use something like this in my component
this.dataSource = this.$CustomStore({ ///... settings...// })
I assume that CustomStore is a function, so you can try using Nuxt.js inject() method. This method will make your functions or values available across your app.
~/plugins/global.js
export default ({ app }, inject) => {
// Inject $CustomStore() in Vue, context and store.
inject('CustomStore', CustomStore)
}
then you can use it across your app components.
your component
mounted() {
this.$CustomStore()
},
reference https://nuxtjs.org/docs/2.x/directory-structure/plugins#inject-in-root--context

How to use VeeValidate or any third party package locally inside vue component

Ok here is the situation, I am working on a SPA with Vue.js. I am using VeeValidate in one of my component say in Component1.vue like this,
import Vue from 'vue';
import VeeValidate from 'vee-validate';
Vue.use(VeeValidate);
export default {
//...
}
In another component say in Component2.vue I am using vuetable-2 which I registered like this,
import Vuetable from 'vuetable-2/src/components/Vuetable';
export default {
components: {
Vuetable
},
//...
}
The problem is that both VeeValidate and Vuetable internally depends on a computed property with same name. And as I am registering VeeValidate globally like Vue.use(VeeValidate);, if I navigate from Component1 to Component2, Vuetable gives an error saying,
The computed property "fields" is already defined as a prop
because VeeValidate already registered itself globally when I landed on Component1.
If I navigate to Component2 from any other component which does not have any dependency with VeeValidate then it works just fine.
So here is my question,
How do I register VeeValidate or any other package inside Component1.vue locally so that it does not influence other components? much like registering other components inside components: {} object.
Vee validate allows you to change the field and error bag names through the configuration. It's in the docs here.
const config = {
errorBagName: 'errors', // change if property conflicts
fieldsBagName: 'fields',
}
Also maybe if interest, the advanced configuration section explains how to inject instances into components instead of globally.

How can I access angular-redux store from child module?

In my angular app I use angular-redux for application state management. In my main module I defined my redux store. Like this:
export class MainModule {
constructor(private ngRedux: NgRedux<MainAppState>,
private devTools: DevToolsExtension) {
let enhancers = [];
if (environment.production === false && devTools.isEnabled()) {
enhancers = [...enhancers, devTools.enhancer()];
}
this.ngRedux.configureStore(
reducer,
{} as MainAppState,
[],
enhancers);
}
}
I created new child module, which contains some components. These components should access to application state. In one of these components I access via #select to store, but this doesn't work. Here is how I access to store:
export function getLanguage(state: LanguageState) { return state.userLanguage; }
And this code I have in my ChildComponent class:
export class ChildComponent implements OnInit {
#select(getLanguage) savedUserLanguage$: Observable<LanguageState>;
// more code
}
How can I access to application state store from child modules? What should I import in child module? Will It be better to create own module only for redux store handling? Maybe I forgot something?
I use Angular v4 and #angular-redux/store v6.
I'd recommend creating a separate module that just contains your store, e.g. StoreModule. You can then import your StoreModule into all your child modules and access your store from there.
This is the way they go in the official example app:
StoreModule: https://github.com/angular-redux/example-app/blob/master/src/app/store/module.ts
Child Module: https://github.com/angular-redux/example-app/blob/master/src/app/elephants/module.ts
Component in child module: https://github.com/angular-redux/example-app/blob/master/src/app/elephants/page.ts
I was thinking about refactoring some ugly old JavaScript code that uses prototypal inheritance into an Angular 7+ project. I was asking myself pretty much the same question. Inspired by my udemy Angular course, I tried an experiment with a ngrx store and lazy loaded modules.
(Keep in mind that ngrx is SIMILAR to #angular-redux, but it's NOT the same thing. See https://ngrx.io/docs for details.)
Here it is.
I create the store in the main module with StoreModule.forRoot and in each lazy loaded module, I create a reference to the store with StoreModule.forFeature.
(See https://ngrx.io/api/store/StoreModule for details.)
When I dispatch actions on the store with the lazy loaded components, those actions (and corresponding reducers) seem to change the value to which the main app component subscribes.
Also, when I dispatch actions on the store with the main app component, those actions (and corresponding reducers) seem to change the value to which the lazy loaded components subscribe.
Also, it's hard to explain what I did in a simple 200-500 character block so I had to use a github project.

Categories

Resources