How can I make my custom modifiers in vuejs and how can I use them?
any idea?
You can create modifiers only for your own custom directives.
Vuejs doesn't allow to add additional modifiers to core directives like v-model, v-on etc.
Example with a custom directive:
<div v-my-directive.uppercase="myVar" />
const myDirective = {
created(el, binding, vnode, prevVnode) {
if(binding.modifiers.uppercase) {
// Do whatever
}
},
}
Sources:
Vuejs documentation: Custom directives
Vuejs issue #3666: Add custom v-model modifier
Related
In order to use a dynamically-defined single page component, we use the component tag, thusly:
<component v-bind:is="componentName" :prop="someProperty"/>
...
import DynamicComponent from '#/components/DynamicComponent.vue';
...
components: {
DynamicComponent
},
props: {
componentName: String,
someProperty: null,
}
The problem is, this isn't really very dynamic at all, since every component we could ever possibly want to use here needs to be not only imported statically, but also registered in components.
We tried doing this, in order at least to avoid the need to import everything:
created() {
import(`#/components/${this.componentName}.vue`);
},
but of course this fails, as it seems that DynamicComponent must be defined before reaching created().
How can we use a component that is truly dynamic, i.e. imported and registered at runtime, given only its name?
From the documentation: Emphasis mine
<!-- Component changes when currentTabComponent changes -->
<component v-bind:is="currentTabComponent"></component>
In the example above, currentTabComponent can contain either:
the name of a registered component,
or a component’s options object
If currentTabComponent is a data property of your component you can simply import the component definition and directly pass it to the component tag without having to define it on the current template.
Here is an example where the component content will change if you click on the Vue logo.
Like this:
<component :is="dynamic" />
...
setComponentName() {
this.dynamic = () => import(`#/components/${this.componentName}.vue`);
},
Solution for Nuxt only
As of now its possible to auto-import components in Nuxt (nuxt/components). If you do so, you have a bunch of components ready to be registered whenever you use them in your vue template e.g.:
<MyComponent some-property="some-value" />
If you want to have truly dynamic components combined with nuxt/components you can make use of the way Nuxt prepares the components automagically. I created a package which enables dynamic components for auto-imported components (you can check it out here: #blokwise/dynamic).
Long story short: with the package you are able to dynamically import your components like this:
<NuxtDynamic :name="componentName" some-property="some-value" />
Where componentName might be 'MyComponent'. The name can either be statically stored in a variable or even be dynamically created through some API call to your backend / CMS.
If you are interested in how the underlying magic works you can checkout this article: Crank up auto import for dynamic Nuxt.js components
According to the official Documentation: Starting from v2.13, Nuxt can auto import your components when used in your templates, to activate this feature, set components: true in your configuration
you are talking about async components. You simply need to use the following syntax to return the component definition with a promise.
Vue.component('componentName', function (resolve, reject) {
requestTemplate().then(function (response) {
// Pass the component definition to the resolve callback
resolve({
template: response
})
});
})
According to quasar docs the custom component used with dialog plugin can have props. But I don't see how to pass those props to the component via
this.$q.dialog({component: CustomComponent,})
The docs state you can add them after the comma like this:
this.$q.dialog({
component: CustomComponent,
// optional if you want to have access to
// Router, Vuex store, and so on, in your
// custom component:
parent: this, // becomes child of this Vue node
// ("this" points to your Vue component)
// (prop was called "root" in < 1.1.0 and
// still works, but recommending to switch
// to the more appropriate "parent" name)
// props forwarded to component
// (everything except "component" and "parent" props above):
text: 'something',
// ...more.props...
is there a way how to write a custom directive in nuxt js, which will work for ssr and also for frontend (or even for ssr only)?
I tried it like in following documentation:
https://nuxtjs.org/api/configuration-render#bundleRenderer
so I added this code:
module.exports = {
render: {
bundleRenderer: {
directives: {
custom1: function (el, dir) {
// something ...
}
}
}
}
}
to nuxt.config.js
then I use it in template as:
<component v-custom1></component>
but it doesn't work, it just throw the frontend error
[Vue warn]: Failed to resolve directive: custom1
And it doesn't seem to be working even on server side.
Thanks for any advice.
If you want use custom directives in Nuxt you can do the following:
Create a file inside plugins folder, for example, directives.js
In nuxt.config.js add something like plugins: ['~/plugins/directives.js']
In your new file add your custom directive like this:
import Vue from 'vue'
Vue.directive('focus', {
inserted: (el) => {
el.focus()
}
})
How To Create A Directive
You can make directives run on the client by adding the .client.js extension to your directives file. This works for SSR and static rendering.
// plugins/directive.client.js
import Vue from 'vue'
Vue.directive('log-inner-text', {
inserted: el => {
console.log(el.innerText)
}
})
How To Insert Directives
In your nuxt.config.js file add it as a plugin like this.
plugins: [
'~/plugins/directive.client.js'
]
Don't forget to save your directive in the plugins folder.
How To Use A Directive
<div v-log-inner-text>Hello</div>
Console logs
> "Hello"
I have written a medium article that goes a lot more in-depth on how this works. It shows you how to make a directive that makes an element animate into view on scroll: Nuxt - Creating Custom Directives For Static & SSR Sites
Tested in nuxt-edge ( its nuxt 2.0 that will be out in this or next month, but its pretty stable as it is).
nuxt.config.js
render: {
bundleRenderer: {
directives: {
cww: function (vnode, dir) {
const style = vnode.data.style || (vnode.data.style = {})
style.backgroundColor = '#ff0016'
}
}
}
}
page.vue
<div v-cww>X</div>
Resulting html from server:
<div style="background-color:#ff0016;">X</div>
For anyone else coming here, the accepted answer allows you to run an SSR-only directive. This is helpful but a little unintuitive if you want to have a directive run everywhere.
If you only use nuxt.config.js to implement a directive via render, it will not be supported on the client-side without also adding a directive plugin and adding it to the config (see the How to Create a Directive Answer).
To test this out, try this experiment:
Follow the instructions to create directive using plugins (make one called loading)
Vue.directive('loading', function (el, binding) {
console.log('running loading directive client side')
})
Add this to your nuxt.config:
render: {
bundleRenderer: {
directives: {
loading (element, binding) {
console.log('running loading directive server side')
}
}
}
}
Use the directive on a Vue page file like:
<div v-loading="true">Test</div>
On page load, you will see both the client-side and SSR directives run. And if you remove the client-side directive, you will see errors thrown like the OP had: [Vue warn]: Failed to resolve directive: loading.
Tested on nuxt 2.12.2.
I use Vuejs2 with a server side rendering, and I have create a plugin. When I declare a directive and use this on a DOM element, I have many warnings, but my directive working:
Here is my code for directive on plugins:
Vue.directive("htl-mouse-tracker", {
bind(el, binding, vnode, oldVnode) {
console.log(el)
}
})
and I use my directive like this:
button(v-on:click="toggleMobileNavigation", v-htl-mouse-tracker).AppHeader__headerButton
I am new to Angular 2, I have injected directive in current Component
#Component({
selector: 'select-me',
templateUrl: 'app/template.html',
directives: [BackgroundChange] // I want to access this same instance to make the dynamic changes
})
export class PageComponent {
constructor(private backgroundChange:BackgroundChange) {
// I guess this will create new instance of BackgroundChange
}
}
I want to call methods availabe in BackgroundChange to do some changes dynamically from PageComponent
Directives are standalone and should be used in your HTML template - not injected into your PageComponent... aka Directives are not injectable.
The BackgroundChange directive will have access to the HTML element it is attached to in your template - and should do its manipulating within.
Angular docs: https://angular.io/docs/ts/latest/guide/attribute-directives.html#!#apply-directive