How to call all Custom Directive globally instead of calling each component? - javascript

I'm setting up a directive for my Vue project on separate individual files.
So far I have succeeded separating files and calling it globally but only possible to do it individually instead of exporting the entire directive and make it global.
**directive.js
const highlight ={
bind(el, binding, vnode) {
... some code
}
const highlight2 ={
... some code
}
export default {
highlight,
highlight
}
**main,js
import Vue from 'vue'
import App from './App.vue'
import * as directive from './directive.js'
Vue.directive(directive);
new Vue({
el: '#app',
render: h => h(App),
directive
})
so far I have been able to call this directive on my main.js but stuck on how to make it globally without calling every single component. like
import { highlight, highlight2} from './directive
Edit:
Found my way by looping through with forEach function.
Object.keys(directive).forEach(function(name){
Vue.directive(name, directive[name])
})

Related

Vue props is undefined when print component dynamically

My problem is on the dynamically creation of the TAG "galeriaimages".
Vue works fine but the props are always undefined
thanks for all.
main.js
import Vue from 'vue'
import Gi from './components/galeriaimages.vue'
import vuetify from './plugins/vuetify';
Vue.config.productionTip = false
document.addEventListener('DOMContentLoaded', function() {
new Vue({vuetify, render: h => h(Gi) }).$mount('galeriaimages');
});
HTML
<galeriaimages p1="awesome" /> <!-- I create it dinamically-->
Vue component
<script>
export default {
props: ['p1'] ,
data: function() {
return {
}
},
created: function() {
alert(this.p1); //this is always undefined
}
}
Thanks to #skirtle for give me the answer :-)
I added this line in my vue.config.js
runtimeCompiler: true
...and all works fine
The bit where you write h(Gi) is creating a galeriaimages component but not passing any props to it.
To pass the prop you would need to write:
new Vue({
vuetify,
render: h => h(Gi, {props: {p1: 'awesome'}})
}).$mount('galeriaimages');
However, I suspect that isn't what you're really trying to do.
You currently seem to be mounting directly to the <galeriaimages> element, which is a bit odd but if you remove the render function it should work. You can also use el instead of $mount:
new Vue({
vuetify,
components: {galeriaimages: Gi},
el: 'galeriaimages'
});
I would add that the reason most examples use a render function for the root Vue instance is that it avoids the need to include the template compiler in the Vue build. This only works if all your other Vue components are pre-built .vue files. If you have any templates at runtime, including those in your HTML, then you'll need to include the template compiler anyway. In that scenario there's no benefit to using a render function on the root instance.
You need to provide the component matching the tag <galeriaimages>. Your custom render function is overriding the template parsing, so it is not parsing the <galeriaimages> as a component tag.
new Vue({vuetify, components: {galeriaimages: Gi} }).$mount('galeriaimages');
Also your components are not creating any elements. They are not able to mount.

How to pass props to Vue from another js module?

Is it possible to pass props from any js module to vue?
Props are passing fine between components for me, but not from the actual Vue app itself:
main.js
import Vue from 'vue'
import App from './App.vue'
var myVue = new Vue({ export to other files
el: '#entry',
components: {App},
render: h => h(App),
data: function(){
return{
testSuccess:'this test was successful!'
}
},
})
window.myVue = myVue // we use window.myVue because if we can export to window, we can export to other js modules.
App.vue
<template>
<div ref="app">
{{ testSuccess ? testSuccess : 'prop not imported!' }}
</div>
</template>
<script>
export default = {
name: "app",
props: ["testSuccess"]
}
</script>
index.html
<div id="entry" >
<app :testSuccess="testSuccess"></app>
</div>
<script src="/dist/build.js"></script>
What am I missing?
I understand how to do this with components.
I want to be able to export the Vue module into other js modules and pass meaningful information to it.
This is the render function for your root Vue instance:
render: h => h(App)
You aren't passing any props to h, so the App will be created without props.
The template inside #entry will be ignored because you're providing an explicit render function.
So either:
Remove the render function from the root Vue instance. Note that the reason most examples use a render function is so that they can use the runtime-only build of Vue, which can't compile templates.
Remove the template from inside #entry and pass the props to App within the render function.
The latter would look like this:
render (h) {
return h(App, { props: { testSuccess: this.testSuccess } })
}
Note this can't use an arrow function because it requires access to this.
Once you're passing the props correctly you should be able to update the value using myVue.testSuccess = '...' no problem.
As you have discovered, you cannot pass props to your $root Vue app. However, you can modify the properties of the Vue instance and Vue will react to those changes.
In your example above, you could write anywhere (including the console):
window.myApp.testSuccess= "I've been changed!";
and the HTML should update.
However, the way you have written your components above mean that the testSuccess property is not being passed into the App.vue component. Instead of making your App.vue a component of the root Vue instance, create them like this:
index.html
<div id="app" >
</div>
<script src="/dist/build.js"></script>
main.js
import Vue from 'vue'
import App from './App.vue'
var myVue = new Vue({ // export to other files
el: '#app',
...App,
})
window.myVue = myVue // we use window.myVue because if we can export to window, we can export to other js modules.
App.vue
<template>
<div>
{{ testSuccess || 'testSuccess is blank!' }}
</div>
</template>
<script>
export default {
data: { // doesn't need to be a function in the root Vue instance
testSuccess: "this is the default text",
...
}
</script>
AN EVEN BETTER WAY
Despite all the above, an even better way is to use proper state management. By placing all your shared state into a dedicated state object (or VueX), any module which has access to the state object can manipulate the state.
Have a read of https://v2.vuejs.org/v2/guide/state-management.html

Pass options to vuejs components registered globally

I am registering my vuejs components in this way:
index.js (A separate reusable npm+webpack project: myComponents)
import MyButtons from './src/components/my-buttons.vue'
import MyInput from './src/components/my-inputs.vue'
export default {
install(Vue, options) {
Vue.component("my-button", MyButtons);
Vue.component("my-input", MyInput);
}
};
Another project where I am using the above components with npm link
import Vue from 'vue'
import App from './vue/App.vue'
import MyComponents from 'myComponents'
Vue.use(MyComponents, {
theme: 'SomeTheme',
color: 'SomeColor'
});
new Vue({el: '#app', render: h => h(App)});
Now what I want to do is in install() function somehow pass the options to the components being registered and save them. So that I can control the color and theme in such a way that every instance of these components render according to the theme and color, where these components will have more then one theme/style and color.
A common way of solving this problem is to put the settings on the Vue prototype.
e.g.:
install(Vue, options) {
Vue.prototype.$myLibraryOrPluginName = { options }
Vue.component("my-button", MyButtons);
Vue.component("my-input", MyInput);
}
Then inside the components you can access the options using:
this.$myLibraryOrPluginName.options.theme
The way I've defined it here the options would not be reactive. You'd need to get Vue.observable involved to add reactivity:
Vue.prototype.$myLibraryOrPluginName = Vue.observable({ options })

Is there a way to use RequireJS when importing VueJS components?

I have a project which uses RequireJS and Vue components. I am trying to modularise the Vue components into smaller parts and I want to be able to export smaller vue components so that they can be used by a bigger one. This is simple with standard vue:
import SomeComponent from './SomeComponent.vue'
new Vue({
el: '#app',
...
components: { SomeComponent },
...
}
but how would this be done with requireJS?
You can use require to import your *.vue components like this:
new Vue({
el: '#app',
...
components: {
'some-component': require('../path/to/components/SomeComponent.vue').default,
...
},
...
});
Your *.vue files should be structured like this:
<template>
<!-- Component HTML -->
</template>
<script>
export default {
name: 'some-component',
...
}
</script>
<style>
/* Component Styles */
</style>
As an alternative, you can use require to register you components globally (see api docs):
Vue.component('some-component', require('../path/to/components/SomeComponent.vue').default);
new Vue({
el: '#app',
... // no need to declare `SomeComponent` here
});
This is a good option if you have several components that will all make use of SomeComponent.
I'm not exactly certain what you are asking, but if you are just trying to modularize, you can do this with import. The way to do this is by importing components into components.
If you have a pagination component that is being imported to your app, you can import a smaller component (a sub-component) into pagination component. You can go as small as you want this way and have sub-sub-sub-components. The syntax for importing components into components is identical to importing components into a new vue page.
Unless I'm missing something, there's no reason to try and use require. Vue already gives you everything you need with the ability to import components. That's the proper way to modularize and keep your code DRY in Vue.

How to import a js class in main.js file of a vue.js project and use it in all the components instead of importing in each component?

I have written some JS classes that I would like to import in the app.js/main.js file of my vue.js project so that I can instantiate them in the components. Right now I am having to import the same JS class in all the components where I need the class individually.
I've tried the import in the main.js file but the components don't recognize it.
in the main.js file, I am importing like as follows
import Permissions from './Permissions'
However, when I want to instantiate the Permissions class in my component like
data() {
permissions: new Permission({
some object properties...
})
}
the component doesn't know what Permissions is.
How do I let the component know what Permissions class is?
To do it in the vue way, you can create your own plugin or mixin. See detailed instructions here
So, you can create a permissions plugin in permissions-plugin.js
import Permissions from './Permissions'
const PermissionsPlugin = {
install(Vue, options) {
// This adds the $getPermissions method to all instances
Vue.prototype.$getPermissions = function(properties) {
return new Permission({
some object properties...
})
}
}
};
Then you have to tell vue to use your plugin:
import Vue from 'vue'
import PermissionsPlugin from './permissions-plugin.js'
import App from './App.vue'
// The plugin is loaded here.
Vue.use(PermissionsPlugin)
new Vue({
el: '#app',
render: h => h(App)
});
And lastly now from any component you should be able to use your function like:
this.$getPermissions(properties)

Categories

Resources