How to make the button animates in vue.js - vue.js

How to animate(toggle) the button it self when click?
I tried as below
<div id="app">
<button class="btn" #click="show = !show">
click
</button>
</div>
<script>
var app = new Vue({
el: '#app',
data: function() {
return {
show: true
}
}
});
</script>
<style>
.button { position:fixed; top:100px; left:100px; }
.button.active { left:0; }
</style>
I expect the output that when click the button, button move to left:0 position. And another click, it move to left 100.

Use class binding to bind the active class when show is true. You should also use the button class instead of btn as that's what you have in your CSS.
var app = new Vue({
el: '#app',
data: {
show: true
}
})
.button {
position: fixed;
top: 100px;
left: 100px;
transition: left 0.2s; /* added this for fun */
}
.button.active {
left: 0;
}
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<button class="button" :class="{active: show}" #click="show = !show">
click
</button>
</div>

Related

Avoid infinite loading spinner in vue js

I have a preloader in Vue js but it's infinite, how could I fix it? I was thinking about doing something to hide the div that contains the preloader when the page is loaded using mounted(), but I am not sure what should I do exactly. I am working in the App.vue file.
EDIT: Tried to add the class d-none when the component is mounted but that didn't work
new Vue({
el: "#app",
data(){
return{
classes: '',
}
},
mounted(){
this.classes='d-none';
}
});
/* Loader */
#preloader {
position: fixed;
left: 0;
top: 0;
z-index: 99999;
width: 100%;
height: 100%;
overflow: visible;
display: table
}
.loader {
display: table-cell;
vertical-align: middle;
position: relative;
width: 200px;
height: 200px
}
#preloader,
.contact-box,
.scroll-to-top {
background: #fff;
text-align: center
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="preloader" v-bind:class="classes">
<div class="row loader">
<img src="https://media2.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" alt="logo" width="220" height="110">
<br><br>
</div>
</div>
<h1>content</h1>
</div>
the best way to do this task in vuejs is using a v-if.
e.g
<div v-if="!isLoaded" id="preloader">
<div class="row loader">
<img src="https://media2.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" alt="logo" width="220" height="110">
<br><br>
</div>
</div>
new Vue({
el: "#app",
data(){
return{
isLoaded: false,
}
},
mounted: function() {
this.$nextTick(q => {
// Will be executed when the DOM is ready
this.isLoaded = true;
// UPD : you can use this instead for your tests ..
// setTimeout(function () { this.isLoaded = true; }, 2000)
})
}
});

vue.js: ":class" cause the classList is wrong

as cood like this
'<div class="item" :class="{'editable':canEdit}"></div>';
set 'canEdit' to false -------the classes of 'div' are "item"
'$("div").addClass("on")' ------the classes of 'div' are "item on"
set 'canEdit' to true -------the classes of 'div' are "item editable"
question:why the classes of 'div' are not "item on editable"
Because you are not using Vue to add class to the element. So Vue doesn't know you have added a new class to the element.
See this example where I add a class NOT using Vue:
new Vue({
el: '#app',
template: `
<div>
<div ref="e" class="a" :class="{ b: b }"></div>
<button #click="toggleB">Toggle B</button>
<button #click="addC">Add C</button>
</div>
`,
data(){
return {
b: true
}
},
methods: {
toggleB(){
this.b = !this.b;
},
addC(){
this.$refs.e.classList.add('c');
}
}
});
.a {
width: 100px;
height: 100px;
}
.b {
border: 1px solid black;
}
.c {
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app"></div>
Now if I use Vue to add class to it, it will work because now Vue knows:
new Vue({
el: '#app',
template: `
<div>
<div class="a" :class="{ b: b, c: c }"></div>
<button #click="toggleB">Toggle B</button>
<button #click="addC">Add C</button>
</div>
`,
data(){
return {
b: true,
c: false
}
},
methods: {
toggleB(){
this.b = !this.b;
},
addC(){
this.c = true;
}
}
});
.a {
width: 100px;
height: 100px;
}
.b {
border: 1px solid black;
}
.c {
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app"></div>

VueJS complex v-if

I want to show a button ONLY if two conditions are met. First I try v-if with only one condition at a time:
v-if="editMode"
v-if="$can('customersdelete')"
using only one condition at a time, the button is display, so i think both conditions are true. If i use:
v-if="editMode && $can('customersdelete')"
The button isn't display. $can is a mixin, to validate user has permission to do something.
<script>
export default {
methods: {
$can(permissionName) {
return Permissions.indexOf(permissionName) !== -1;
},
},
};
</script>
I don't know why this is not working...
Apparently, any subsequent v-if is ignored and only the first one is taken into account, as demonstrated by the following example:
Vue.config.devtools = false;
Vue.config.productionTip = false;
const Permissions = ['customersdelete'];
new Vue({
el: '#app',
data() {
return { editMode: true };
},
methods: {
$can(permissionName) {
return Permissions.indexOf(permissionName) !== -1;
},
},
})
code {
background-color: #f5f5f5;
border: 1px solid #eee;
padding: 2px 5px;
color: red;
border-radius: 3px;
display: inline-block;
}
div {
margin-top: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<label><input type="checkbox" v-model="editMode">editMode</label><br><br>
<div>$can('customersdelete') => <code v-text="$can('customersdelete')"></code></div>
<div>editMode => <code v-text="editMode"></code></div>
<hr />
<div v-if="$can('customersdelete')">
<code>v-if="$can('customersdelete')"</code>
</div>
<div v-if="editMode">
<code v-if="editMode">v-if="editMode"</code>
</div>
<div v-if="editMode && $can('customersdelete')">
<code>v-if="editMode && $can('customersdelete')"</code>
</div>
<div v-if="editMode"
v-if="$can('customersdelete')">
<code>v-if="editMode" v-if="$can('customersdelete')"</code>
</div>
<div v-if="$can('customersdelete')"
v-if="editMode">
<code>v-if="$can('customersdelete')" v-if="editMode"</code>
</div>
</div>
I would suggest use function and then use in v-if.
example
v-if="isButtonShow()"
and below is the method portion:
methods:{
isButtonShow(){
if(this.editMode){
if(this.$can('customersdelete'){
return true;
}
}
return false;
}
}

Hide div when clicking the main div, but not when clicking child divs, hrefs, spans etc

So, when you click the blue content, I want to hide it, but not if you click a child element, like a h2, a, p, etc. Is this possible?
Please see the fiddle
html
<html>
<head></head>
<body>
<div id="app">
<div v-if="modal" id="content" #click="toggle">
<h3>
Name
</h3>
<span>
Like this (don't close if clicked)
</span>
</div>
<button #click="toggle">Toggle</button>
</div>
</body>
</html>
.js
new Vue({
el: '#app',
data: {
modal: true
},
methods: {
toggle: function( ){
this.modal = !this.modal
}
}
});
.css
a {
color: white
}
#content {
width: 300px;
height: 300px;
background: blue;
color: white;
}
Fiddle: http://jsfiddle.net/awu752mr/6/
I believe that is what the v-on:click.self modifier does. See here in the docs.
As #LShapz answered, the modifier=.self should be the recommended approach (Vue Style).
Another way is compare $event.target === $event.currentTarget (not recommended for your use case, but you may use these two properties for some other situations in future).
Vue.config.productionTip = false
new Vue({
el: '#app',
data: {
modal: true
},
methods: {
toggle: function(ev){
if(ev.target === ev.currentTarget) this.modal = !this.modal
}
}
});
a {
color: white
}
#content {
width: 300px;
height: 300px;
background: blue;
color: white;
}
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<div v-if="modal" id="content" #click="toggle($event)">
<h3>
Name
</h3>
<span>
Like this
</span>
</div>
<button #click="toggle">Toggle</button>
</div>

Accessing Vue Component scope from external javascript

Can I access Vue components data properties and methods from external javascript? I am trying to create a hybrid application where a portion of the screen is a Vue component, and I want to call a method inside that component on click of a button which is handled by pure js. Is there a way to achieve this?
Thanks!
Yes. You need to assign your Vue object to a variable (i.e. vue) and then you can access vue.methodName() and vue.propertyName:
// add you new Vue object to a variable
const vue = new Vue({
el: "#app",
data: {
todos: [
{ text: "Learn JavaScript", done: false },
{ text: "Learn Vue", done: false },
{ text: "Play around in JSFiddle", done: true },
{ text: "Build something awesome", done: true }
]
},
methods: {
toggle: function(todo){
todo.done = !todo.done
}
}
});
// Add event listener to outside button
const button = document.getElementById('outsideButton');
button.addEventListener('click', function() {
vue.toggle(vue.todos[1]);
});
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://unpkg.com/vue#2.5.16/dist/vue.min.js"></script>
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="todo in todos">
<label>
<input type="checkbox"
v-on:change="toggle(todo)"
v-bind:checked="todo.done">
<del v-if="todo.done">
{{ todo.text }}
</del>
<span v-else>
{{ todo.text }}
</span>
</label>
</li>
</ol>
</div>
<div class="outside">
<button id="outsideButton">
Click outside button
</button>
</div>
Yes, you can add an event listener to the Vue component that listens for the button click's event. See example here on codepen.
JS
new Vue({
el: '#app',
methods: {
clickMethod(event){
if (event.target.id === 'outsideButton') {
alert('button clicked')
}
}
},
created(){
let localThis = this
document.addEventListener('click', this.clickMethod)
}
})
HTML
<div>
<button id="outsideButton">Button</button>
<div id="app">
</div>
</div>