Unable to disable click event of a span - vue.js

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>

Related

Window is not defined in nuxt js

So, I wanted to bind style with the height of another element that I got from getHeight function, but I kept getting an error that said window is not defined.
Can someone please give me a solution?
Here is my source code:
<template>
<div class="container">
<p class="section-title">past event</p>
<div class="columns is-multiline">
<div
class="column is-one-third is-centered past-events"
v-for="(event, index) in events.slice(0, 2)"
:key="index"
>
<EventCard :event="event" />
</div>
<div class="column is-one-third is-centered">
<div class="link-box" :style="{ height: getHeight() }">
<nuxt-link to="/past-events">
<p style="color: #ffffff; cursor: pointer" class="see-all">
Lihat List Event Lainnya
</p>
</nuxt-link>
</div>
</div>
</div>
<a class="see-all-btn"> </a>
</div>
</template>
<script>
import EventCard from "~/components/EventCard.vue";
export default {
name: "PastEvents",
components: {
EventCard
},
props: ["events"],
data() {
return {};
},
mounted() {
this.getHeight();
},
methods: {
getHeight() {
const height = window.getComputedStyle(
document.querySelector(".past-events")
).height;
console.log(height);
return height + "px";
}
}
};
</script>
Nuxt uses server-sided rendering. This means that when your code is being executed on the server, it does not have something like window. After all, it is not a browser.
The easiest way around this is by wrapping anything that should not be pre-rendered to html, with something like vue-no-ssr. This particular library renders a dummy component on the server, then actually renders the component when it gets to the browser.
Yes window doesn't exist during the mounted lifecycle hook. I assume you're trying to place something based on its position?
In that case, you might be able to utilize CSS to do it for you. You can place elements using the View Height/View Width units. Combine that with CSS calc() and you might get the solution you need.
Example:
.element {
/* make element positon relative to the window */
position: fixed;
/* set position - note vw/vh are % of window */
/* this put the top of your element -200px from the bottom of your window */
top: calc(100vh - 200px);
}
If you're doing something more complex, using Javascript's element.getBoundingClientRect() will likely provide what you need. See this answer for more info.

ElementUI datetime picker update on popper close

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>

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>

Add class only on mobile - Vuejs and bootstrap

I want to add a class only on mobile. I have done this before using vuetify however it seems more difficult with vue:
code:
<div class="{'mobileSnackBar': breakpoint.xs}">
<p> This is my snackbar </p>
</div>
in vuetify you have the $vuetify.breakpoint.xs however how would i get a similar effect with bootstrap? Or please recommend an alternative.
With vuetify you can do:
computed: {
is_screen_small() {
return this.$vuetify.breakpoint.smOnly
},
}
And combine it like this:
<div class="{'mobileSnackBar': is_screen_small}">
<p> This is my snackbar </p>
</div>
Please make sure you read vuetify docs for breakpoints to know more.
However as I know with bootstrap the only way is to use media queries:
// Small devices
#media (max-width: 760px) {
//Add your style here
}
Though, there is a solution which is not related to bootstrap:
computed: {
is_mobile() {
const isMobile = window.matchMedia("only screen and (max-width: 760px)")
return isMobile.matches ? true : false
}
}
And combine it like :
<div class="{'mobileSnackBar': is_mobile}">
<p> This is my snackbar </p>
</div>
Another way with bootstrap is to use the breakpoint classes to show/hide elements, something like this:
<div class="mobileSnackBar d-sm-none">
<p> This is my snackbar </p>
</div>
<div class="d-none d-sm-block">
<p> This is my snackbar </p>
</div>
Makes more sense with components rather than html, and maybe even then not the cleanest solution, but it does work.

How to customize style of VueJS 2.0 using stylus?

I am using v-text-field without vuetify.min.css just use stylus.
Here is my code.
<template>
<v-text-field type="text" name="password"></v-text-field>
</template>
<style lang="stylus" scoped="scoped">
.input-group_details {
XXX
}
</style>
I am trying to hide some divs in v-text-field.
But I got nothing changed.
That is not possible using scoped styles (That's the point of scoping)
What you could do is either passing down a prop which indicates that the divs are hidden or handle it globally.
passing down a prop:
const textField = {
template: `
<div>
<div>Always shown</div>
<div v-if="shown">
Conditionally shown
</div>
</div>
`,
props: { shown: Boolean }
};
Vue.component('v-text-field', textField);
new Vue({}).$mount('#app');
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
<b>shown = true:</b>
<v-text-field :shown="true"></v-text-field>
<br>
<b>shown = false:</b>
<v-text-field :shown="false"></v-text-field>
</div>
As per https://vue-loader.vuejs.org/en/features/scoped-css.html#notes
you need to use >>> operator for CSS
So this should work:
<style scoped>
>>> .input-group_details {
//your css
}
</style>
You can use lang="stylus" and it will work, but your IDE might throw some syntax errors.
I'm not sure what's correct stylus syntax for that.
Note that it was implemented in v12.2.0