I have this vue 2 cli directive
directives: {
swipe: {
inserted: function runme(el) {
alert(el);
},
},
},
How can I run runme(obj) from methods or another directive
You could factor out the common code into its own standalone method that could be called from anywhere:
function swipeInserted(el, binding, vnode) {
alert(el)
}
export default {
directives: {
swipe: {
inserted: swipeInserted,
},
other: {
inserted(el, binding, vnode) {
swipeInserted(el, binding, vnode)
// other code specific to this directive...
}
}
},
methods: {
runInserted() {
const el = {/*...*/}
const binding = {/*...*/}
const vnode = {/*...*/}
swipeInserted(el, binding, vnode)
}
}
}
Related
I need to write a specific global directive that should perform the same function in different hooks.
How can I implement something like this
export default {
directives: {
widthAsChild: {
widthAsChild(el) {
el.style.width = getComputedStyle(el.firstChild).getPropertyValue(
"width"
);
},
mounted(el) {
widthAsChild(el);
window.addEventListener("resize", () => {
widthAsChild(el);
});
},
},
},
}
The function has to be declared outside the directive's declaration object. One way to do that is to use an IIFE that contains a local method that you can can reuse in the returned directive declaration:
export default {
directives: {
widthAsChild: (() => {
const widthAsChild = el => {
el.style.width = getComputedStyle(el.firstChild).getPropertyValue("width");
}
return {
mounted(el) {
widthAsChild(el);
window.addEventListener("resize", () => {
widthAsChild(el);
});
},
}
})()
}
}
demo 1
Alternatively, you could move that to a separate file:
// #/directives/widthAsChild.js
const widthAsChild = el => {
el.style.width = getComputedStyle(el.firstChild).getPropertyValue('width')
}
export default {
mounted(el) {
widthAsChild(el)
window.addEventListener('resize', () => {
widthAsChild(el)
})
}
}
// MyComponent.vue
import widthAsChild from '#/directives/widthAsChild'
export default {
directives: {
widthAsChild,
}
}
demo 2
I have this script in the component
<script>
export default {
name: "Auth",
data() {
return {
page: 0,
};
},
methods: {
},
mounted() {
this.page = 3; //works
},
directives: {
swipe: {
loaded: {
function(el, binding) {
alert(this.page == data.binding.page); //doesen't work
},
},
},
},
};
</script>
But in the chrome i have an error
TypeError: Cannot read property 'page' of undefined
So why this is undefined?
The directive hook can access the component through the vnode argument:
export default {
directives: {
swipe: {
inserted(el, binding, vnode) {
console.log(vnode.context.page)
}
}
}
}
I'm trying to take this Flickr jsonp Vue example (https://codepen.io/tomascherry/pen/GrgbzQ) and turn it into a component. However, I cannot figure out how to get jsonFlickrFeed() to map to this.jsonFlickrFeed() (once that function is place inside the component's methods: {}).
Code as follows:
<template>
<!-- HTML HERE -->
</template>
<script>
let callApiTimeout = null
export default {
name: 'Flickr',
filters: {
splitTags: function(value) {
// showing only first 5 tags
return value.split(' ').slice(0, 5)
}
},
directives: {
/* VueJs utilites */
img: {
inserted: function(el, binding) {
this.lazyload(el, binding)
},
update: function(el, binding) {
this.lazyload(el, binding)
}
}
},
data() {
return {
images: [],
query: ''
}
},
watch: {
query: function(value) {
clearTimeout(callApiTimeout)
callApiTimeout = setTimeout(
function() {
const reqURL =
'https://api.flickr.com/services/feeds/photos_public.gne'
const options = {
params: {
format: 'json',
tags: this.query,
jsoncallback: 'this.jsonFlickrFeed'
}
}
this.$http.jsonp(reqURL, options)
}.bind(this),
250
)
}
},
methods: {
/* JSONP callback function */
jsonFlickrFeed(response) {
this.$data.images = response.items
},
/* General utility functions */
lazyload(el, binding) {
const img = new Image()
img.src = binding.value
img.onload = function() {
el.src = binding.value
}
}
}
}
</script>
<style lang="less">
/* STYLE HERE */
</style>
I tried adding the jsoncallback: 'this.jsonFlickrFeed' parameter but that doesn't help.
To make it simpler, just pass the parameter nojsoncallback=1 and it will return the JSON object directly.
I want to create a directive for auto add the icon inside the button.
When user click on it.
But How to pass the loading value(it's boolean data) from the parent object?
Vue.directive('loading', {
bind: function (el, binding, vnode) {
if (binding.value) {
var loadingElement = Vue.extend({
props:['isLoading'],
template: '<span class="loading" v-if="isLoading"><fa-icon :icon="[\'fab\', \'facebook-f\']"></fa-icon></span>',
});
var loadingComponent = new loadingElement({
propsData: {
isLoading: binding.value
}
});
loadingComponent.$mount();
el.appendChild(loadingComponent.$el);
}
},
update: function (el, binding, vnode) {
el.disabled = binding.value;
}
});
I want isLoading: binding.value data is bind from the parent.
I have this Vue code:
export default {
data: function() {
return {
'showPopup': false
}
},
components: {
'search-bar': SearchBarComponent,
},
mounted: function() {
$(this.$el).foundation();
},
updated: function() {
$(this.$el).foundation();
},
methods: {
clickOutsidePopup: function(event) {
console.log(event);
}
},
directives: {
clickoutside: {
bind (el) {
el.event = event => el.vm.$emit(el.expression, event)
el.addEventListener('click', el.stopProp)
document.body.addEventListener('click', event)
},
unbind(el) {
el.removeEventListener('click', el.stopProp)
document.body.removeEventListener('click', el.event)
},
stopProp(event) { event.stopPropagation() }
}
}
}
And inside the template I have this:
<div class="small-screen popup-container">
<div class="popup" v-show="showPopup" v-clickoutside="clickOutsidePopup">
<search-bar />
</div>
</div>
which will be shown/hidden if we click on this:
<span #click="showPopup = !showPopup">🔍</span>
My problem is that my directive does not execute clickOutsidePopup. When I click outside of my element? I was inspired by this: Detect click outside element
I managed to make it work with this directive code:
directives: {
clickoutside: {
bind: function (el, binding, vnode) {
el.clickOutsideEvent = function (event) {
// here I check that click was outside the el and his childrens
if (!(el == event.target || el.contains(event.target))) {
// and if it did, call method provided in attribute value
vnode.context[binding.expression](event);
}
};
document.body.addEventListener('click', el.clickOutsideEvent)
},
unbind: function (el) {
document.body.removeEventListener('click', el.clickOutsideEvent)
},
}
}
added an id to the search button:
<span id="top-bar-search-icon" #click="showPopup = !sho wPopup">🔍</span>
and modified my method:
methods: {
clickOutsidePopup: function(event) {
if (event.target.id !== "top-bar-search-icon")
this.showPopup = false;
}
},