ElementUI datetime picker update on popper close - vue.js

I'm using ElementUI with Vue.js.
What I want to do is to use el-date-picker and listen for the update of the input only when the picker's popper closes (so earlier updates when selecting date via mouse click / direct text edit or via keyboard arrow controls won't trigger my 'special' update) - is it easily achievable? I was thinking of using custom popper class but not sure how to listen for close event to detect it.

You can achieve what you want with the blur event : https://element.eleme.io/#/en-US/component/date-picker#events
Here is a Codepen if you want to play with it. And here is the code if you just want to run it :
var Main = {
methods: {
blur () {
console.log('hey')
}
},
data() {
return {
value1: ''
};
}
};
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
#import url("//unpkg.com/element-ui#2.8.2/lib/theme-chalk/index.css");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="//unpkg.com/vue/dist/vue.js"></script>
<script src="//unpkg.com/element-ui#2.8.2/lib/index.js"></script>
<div id="app">
<template>
<div class="block">
<span class="demonstration">Default</span>
<el-date-picker
v-model="value1"
type="date"
#blur="blur"
placeholder="Pick a day">
</el-date-picker>
</div>
</template>
</div>

Related

Vue - display/create component from a function

One thing that I have been struggling to figure out how to do better is modals. Currently, I am registering the modal component on each Vue that needs it. However, this feels rather sloppy, as I am having to register the component several times. Even using mix-ins just does not feel like an elegant solution. What would be optimal to be able to do is to mimic JavaScript's alert() method on the Vue instance. For example, be able to call this.ShowModal(Header, Body)
However, from my understanding, there is no way to accomplish this
Take for example my Modal example. You could have a modal template like this:
<script type="text/x-template" id="modal-template">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot>
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" #click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</script>
Then you would have to reference the component over and over again like this
<template>
<button #click="displayModal">Display the Modal Alert</button>
<modal v-if="showModal" #close="showModal = false">
<h3 slot="header"> This is a good header </h3>
<p>
Look at me I am the body! You have seen me {{displayCount}} times!
</p>
</modal>
</template>
<script>
components: {modal},
data: {
showModal: false,
displayCount: 0
},
methods: {
displayModal(){
this.displayCount++
this.showModal = true;
}
}
</script>
If you wanted to reuse the component for several messages from within the parent you would then have to add several more variables to store things such as the header and body. You could put some of the logic into a mixin but you would still have to have the clutter of adding the modal component and possibly the mixin.
This brings us to the question. Is there a way to create a function in the Vue instance that would allow for us to dynamically create a Modal component and fill in the slots with arguments passed to the function? e.g. this.ShowModal("This is a good header", "Look at me I am the body!")
Use Vue.extend() create a "modal" constructor and create a instance,you can mount it to DOM dynamically by $mount or other ways
In Modal example:
modal.vue:
<template>
<div>
{{message}} //your modal content
</div>
</template>
<script>
export default {
name: 'modal',
data(){
return {
message: '',
}
},
methods:{
/************/
close () {
/****this.$destroy()****/
}
}
}
</script>
modal.js:
import myModal from 'modal.vue'
import Vue from 'vue'
const modalConstructor = Vue.extend(myModal)
const modal = (options,DOM)=>{
const modalInstance = new modalConstructor({data:options})
modalInstance.vm = modalInstance.$mount() //get vm
const dom = DOM || document.body // default DOM is body
dom.appendChild(modalInstance.vm.$el) // mount to DOM
return modalInstance.vm
}
export default modal
now you can create a Modal component by a function like this:
import showModal from 'modal.js'
showModal({message:"..."})

Unable to disable click event of a span

I am trying to disable a span. My attempt is as below.
<span #click="confirm" disabled="true">click here</span>
But it will not disabled. Where I was wrong and how can I fix this?
You can use css class to disable the span. If you want to make it dynamic simply use Class Binding eg :class="your_variable"
For Class and Style Bindings you can use this reference
vuejs.org/v2/guide/class-and-style.html#Object-Syntax
Class and Style Bindings
const app = new Vue({
methods: {
confirm(){
alert('hello');
}
}
})
app.$mount("#app")
.disable-click{
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Enable click</h2>
<span v-on:click="confirm()">Click</span>
<h2>Disable click</h2>
<span v-on:click="confirm()" class="disable-click">Disable Click</span>
</div>

How to fix my simple custom v-on directive that does not execute a method immediately?

I am here to ask some help about why is my custom directive not working properly. I am trying to create my own v-on (named v-myOn) directive that would just change the background color of the text when it is clicked. The problem is that the method is executed instantly when vue js application is started (meaning the element background has the color style already) and not when a certain event happened which is when the element is clicked. Thanks in advance!
Update: Problem as what Phil stated is I execute the function directly in the template. But in this case I am trying to pass an argument to the method changeColor. So how could i prevent it from executing while being able to pass arguments?
Here is my code in App.vue:
<template>
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
<h1 v-myOn:click="changeColor('blue')" :style="{background: color}" ref="heading">Directives Exercise</h1>
<!-- Exercise -->
<!-- Build a Custom Directive which works like v-on (Listen for Events) -->
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return{
color: ''
}
},
directives: {
myOn : {
bind(el, binding, vnode) {
el.addEventListener(binding.arg, binding.value)
}
}
},
methods: {
changeColor(color)
{
this.color = color;
}
}
}
</script>
<style>
</style>
You have to wrap in an arrow function otherwise it will get executed immediately as you have discovered and #Phil has pointed out.
<h1 v-myOn:click="() => changeColor('blue')" :style="{background: color}" ref="heading">Directives Exercise</h1>

Not able to add #keyup listener to layout component

So I have my outer default.vue layout in nuxt architecture. I'my trying to add #keyup.esc="test" to outer element of default.vue:
<template>
<div #keyup.esc="test">
<navigation></navigation>
<nuxt/>
<transition name="fade">
<overlay-modals v-if="showModalLogin || showModalRegister"></overlay-modals>
</transition>
<transition name="zoom">
<div class="modal__outer" v-if="showModalRegister || showModalLogin">
<modal-login v-if="showModalLogin"></modal-login>
<modal-register v-if="showModalRegister"></modal-register>
</div>
</transition>
</div>
</template>
methods: {
test() {
alert('come on...');
},
test method is never fired which makes me confused.
The keyup event will only be detected by the div when the div has focus, so you have to set tabindex to make it focusable, and you have to give it focus.
new Vue({
el: '#app',
methods: {
test() {
console.log("Come on");
}
},
mounted() {
this.$el.focus();
}
});
<script src="https://unpkg.com/vue#latest/dist/vue.js"></script>
<div id="app" #keyup.esc="test" tabindex="0">
Here is my div
</div>
if u look into documentation u will see that #keyup used in inputs. In your case - u are using this to div, and there is no focus on it so keyup will not possible. However u need to add some stuff to make it working. Please read this

Animating a Vue component using mouseover and mouseout

I am trying to create a Vue component that bounces when the mouse cursor hover over it. I am using the animate.css library and changing the component class with #mouseover then resetting it on #mouseout.
It is almost ok. The only issue occurs when the user stops the cursor near the border. Due to the animation behavior, the mouseover/mouseout events will be called repeatedly, causing the component to flick. I could minimize it using a timeout before resetting the class but the behavior is still uncertain sometimes.
Is there any elegant way (or Vue way) to solve it?
Here is my code:
Html:
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css">
</head>
<body>
<div id="app">
<h1>Hover the mouse near the border</h1>
<hr>
<button :class="classes"
#mouseover="hoverOver"
#mouseout="hoverOut"
>
IMMEDIATE
</button>
<br><br><br>
<button :class="classes"
#mouseover="hoverOver"
#mouseout="hoverOutTimeout"
>
WAIT JUST A BIT
</button>
</div>
</body>
Javascript:
new Vue({
el: "#app",
data: {
classes: []
},
methods: {
hoverOver: function() {
console.log('over');
this.classes = ['animated', 'bounceIn']
},
hoverOut: function() {
console.log('out');
this.classes = []
},
hoverOutTimeout: function() {
setTimeout(() => {
console.log('out');
this.classes = []
}, 1000);
},
}
})
https://jsfiddle.net/marcellorvalle/eywraw8t/477611/
Neat. Looks like as the button changes size during the animation, the mouse goes in and out of hover state because the edge is moving.
I added a div around each button, and attached the hover triggers to the divs instead of the buttons:
<body>
<div id="app">
<h1>Hover the mouse near the border</h1>
<hr>
<div #mouseover="hoverOver" #mouseout="hoverOut">
<button :class="classes">IMMEDIATE</button>
</div>
<br><br><br>
<div #mouseover="hoverOver" #mouseout="hoverOutTimeout">
<button :class="classes">WAIT JUST A BIT
</button>
</div>
</div>
</body>
https://jsfiddle.net/jmbldwn/kbswLpto/5/