How can I show div onlick in Vue.js? - vue.js

I want to display divreg template when someone click this button. My problem is that I dont know how to write in in this method.
const divreg = {
name: "divreg",
template: `
<div>
Hello
</div> `
};
var app = new Vue({
el: "#app",
components: {
divreg
},
data: {
message: "Załóż konto!"
},
methods: {
handleClick() {
//here I need to code to show this template onlick
}
},
template: `
<div>
<h1> {{message}} </h1>
<divreg />
<button #click="handleClick"> Zarejestruj się</button>
</div>
`
});

you can use v-if to show or hide the element, in your case it will something like this:
<divreg v-if="showElement" />
<button #click="handleClick"> Zarejestruj się</button>
data: () => ({
showElement: false
})
methods: {
handleClick() {
this.showElement = true
}
}

<template>
<divreg v-if="showElement" />
<button #click="showElement !== showElement">Zarejestruj się</button>
</template>
<script>
export default {
data: () => ({
showElement: false
}),
}
</script>

Related

how to send click button's value to a props

In my parent component I have a button and child component:
<div> #click="editMe(edit)" />
<edit-team :openModal="openModal"/>
</div>
export default {
data() {
return {
openModal: false,
};
},
method: {
editMe(edit) {
this.openModal = true;
},
}
}
So after I click the editMe button, I am expecting openModal becomes true and goes true to child component.
<template>
<el-dialog
:visible.sync="modal"
/>
</template>
<script>
export default {
props: {
openModal: {
type: Boolean,
required: true,
},
},
data() {
return {
modal: this.openModal,
};
},
</script>
But unfortunately, the modal is not opening because props comes as false always. I assigned openModal to new variable because it was giving me a warning about mutating props. So how do you think I can send the props in right value?
In child just try this
<template>
<el-dialog
:visible.sync="openModal"
/>
</template>
<script>
export default {
props: {
openModal: {
type: Boolean,
required: true,
},
},
},
</script>
If you have sibilngs components and you need to retrieve data, you can use the emit keyword and emit events
Then it will work like this :
The sibling emit the event to show the modal
The parent update the showModalData to true
This child is re-rendered
Vue.component('modal', {
template: '#modal',
props: ['show'],
});
Vue.component('buttonModal', {
template: '#buttonModal',
methods: {
showModal(){
this.$emit('show-modal-button', true)
}
}
});
new Vue({
el: '#app',
data: () => ({
showModalData: false
}),
methods: {
editMe() {
this.showModalData = true
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<p>this is the parent</p>
<hr>
<button-modal #show-modal-button="editMe">Show modal</button-modal>
<hr>
<modal :show="showModalData" />
</div>
<template id="modal">
<div>
props show : {{ show }}
<h2 v-if="show">This is the modal</h2>
</div>
</template>
<template id="buttonModal">
<div>
<p>This is the sibilng</p>
<button #click="showModal"> Show the modal through sibiling components </button>
</div>
</template>

How can I use the method from other component

I want use the method 'pause()' in the component 'vue-count-to',but the webstorm tips Unresolved function or method pause() .How can I use the method in 'vue-count-to'?Thank you
<template>
<div>
<countTo ref="countTo1" :startVal='startVal' :endVal='endVal' :duration='3000'>
</countTo>
<input type="text" v-model="endVal">
<Button v-on:click="handleClick" >reset</Button>
</div>
</template>
<script>
import CountTox from 'vue-count-to';
export default {
components: {
countTo: CountTox},
data () {
return {
startVal: 0,
endVal: 2017,
autoplay: false
}
},
methods: {
handleClick() {
this.$refs.countTo1.pause();
}
}
}
</script>
you can use $root.$emit() and $root.$on()
const componentA = {
template: `
<button #click="callMethodInComponentB">
call method in component-b
</button>
`,
methods: {
callMethodInComponentB() {
this.$root.$emit('call-to-component-b', 2);
}
}
}
const componentB = {
template: `
<h1>Value: {{ value.toString() }}</h1>
`,
data(){
return {
value: 0
}
},
methods: {
plus(add) {
this.value += add
}
},
mounted() {
this.$root.$on('call-to-component-b', add => {
this.plus(add)
});
}
};
new Vue({
el: '#app',
components: {
componentA,
componentB
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<main id="app">
<component-a></component-a>
<component-b></component-b>
</main>
define the method in App.vue and access it from probs and emit

How to add vue.js component multiple times #click?

I'm new to Vue and have been trying to figure this out for days without finding a solution that works...
How do I add an external vue-component multiple times #click on button?
Hopefully my pseudo-code below will explain what i'm trying to do.
<template>
<div>
<Piece/>
<!-- HERE I WANT TO ADD MULTIPLE "<Piece/>" #click on below button -->
<button type="button" #click="addPiece">Add Piece</button>
</div>
</template>
<script>
import Piece from "#/components/Piece.vue";
export default {
name: "PiecesModal",
components: {
Piece,
},
methods: {
addPiece () {
this.components.push(Piece)
}
},
};
</script>
Vue is "data driven"
Instead of wasting time "figuring this out for days", just read the excellent docs, List Rendering in this case...
const piece = Vue.component('Piece', {
props: ['number'],
template: `<div> Piece {{ number }} </div>`
})
const app = new Vue({
el: "#app",
components: { piece },
data() {
return {
counter: 0,
pieces: []
}
},
methods: {
addPiece() {
this.pieces.push(this.counter)
this.counter++
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button type="button" #click="addPiece">Add Piece</button>
<hr>
<Piece v-for="piece in pieces" :key="piece" :number="piece"/>
</div>

vue.js – get new data information

I'm building a chrome extension using vue.js. In one of my vue components I get tab informations of the current tab and wanna display this information in my template. This is my code:
<template>
<div>
<p>{{ tab.url }}</p>
</div>
</template>
<script>
export default {
data() {
return {
tab: {},
};
},
created: function() {
chrome.tabs.query({ active: true, windowId: chrome.windows.WINDOW_ID_CURRENT }, function(tabs) {
this.tab = tabs[0];
});
},
};
</script>
The Problem is, that the template gets the data before it's filled through the function. What is the best solution for this problem, when the tab data doesn't change after it is set once.
Do I have to use the watched property, although the data is only changed once?
// EDITED:
I've implemented the solution, but it still doesn't work. Here is my code:
<template>
<div>
<div v-if="tabInfo">
<p>set time limit for:</p>
<p>{{ tabInfo.url }}</p>
</div>
<div v-else> loading... </div>
</div>
</template>
<script>
export default {
data() {
return {
tabInfo: null,
};
},
mounted() {
this.getData();
},
methods: {
getData() {
chrome.tabs.query({ active: true, windowId: chrome.windows.WINDOW_ID_CURRENT }, function(tabs) {
console.log(tabs[0]);
this.tabInfo = tabs[0];
});
},
},
};
</script>
The console.log statement in my getData function writes the correct object in the console. But the template only shows the else case (loading...).
// EDIT EDIT
Found the error: I used 'this' in the callback function to reference my data but the context of this inside the callback function is an other one.
So the solution is to use
let self = this;
before the callback function and reference the data with
self.tab
You could initialize tab to null (instead of {}) and use v-if="tabs" in your template, similar to this:
// template
<template>
<div v-if="tab">
{{ tab.label }}
<p>{{ tab.body }}</p>
</div>
</template>
// script
data() {
return {
tab: null,
}
}
new Vue({
el: '#app',
data() {
return {
tab: null,
}
},
mounted() {
this.getData();
},
methods: {
getData() {
fetch('https://reqres.in/api/users/2?delay=1')
.then(resp => resp.json())
.then(user => this.tab = user.data)
.catch(err => console.error(err));
}
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<div v-if="tab">
<img :src="tab.avatar" width="200">
<p>{{tab.first_name}} {{tab.last_name}}</p>
</div>
<div v-else>Loading...</div>
</div>

Focus input of freshly added item

So I have a list of items and list of inputs linked to each item via v-for and v-model.
I click a button and add new item to that list. I want to focus input which is linked to newly added item.
Can't figure out how to achieve this goal.
<div id="app">
<div v-for="item in sortedItems">
<input v-model="item">
</div>
<button #click="addItem">
add
</button>
</div>
new Vue({
el: '#app',
data: {
items: []
},
methods: {
addItem: function() {
this.items.push(Math.random());
}
},
computed: {
sortedItems: function() {
return this.items.sort(function(i1, i2) {
return i1 - i2;
})
}
}
})
Here's fiddle with sorted list
https://jsfiddle.net/sfL91r95/1/
Thanks
Update: inspired by pkawiak's comment, a directive-based solution. I found that calling focus in the bind section didn't work; I had to use nextTick to delay it.
Vue.directive('focus-on-create', {
// Note: using Vue 1. In Vue 2, el would be a parameter
bind: function() {
Vue.nextTick(() => {
this.el.focus();
})
}
})
new Vue({
el: '#app',
data: {
items: []
},
methods: {
addItem: function() {
this.items.push(Math.random());
}
},
computed: {
sortedItems: function() {
return this.items.sort(function(i1, i2) {
return i1 - i2;
})
}
}
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div id="app">
<div v-for="item in sortedItems">
<input v-focus-on-create v-model="item">
</div>
<button #click="addItem">
add
</button>
</div>
Original answer:
Make your input a component so that you can give it a ready hook.
const autofocus = Vue.extend({
template: '<input v-model="item" />',
props: ['item'],
ready: function() {
this.$el.focus();
}
})
new Vue({
el: '#app',
data: {
items: []
},
methods: {
addItem: function() {
this.items.push(Math.random());
}
},
components: {
autofocus
},
computed: {
sortedItems: function() {
return this.items.sort(function(i1, i2) {
return i1 - i2;
})
}
}
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div id="app">
<div v-for="item in sortedItems">
<autofocus :item="item"></autofocus>
</div>
<button #click="addItem">
add
</button>
</div>
I Like to extend #Roy's answer.
if you are using any UI framework then it will create DIV and within the DIV input tag will be created so this Snippet will handle that case.
Vue.directive('focus-on-create', {
bind: function(el) {
Vue.nextTick(() => {
el.querySelector('input').focus()
})
}
})