I'm doing an internet-shop app in vue and when I add to cart certain products, I need to show a text, that will show ,that element is added to cart. But afer some time, I need to hide the text. How can I do that?
,when you click on Add to cart button,this text shows up.
added to cart!
In mounted I tried this:
mounted() {
setTimeout(()=>{
this.isAdded=false
},1000)
}
but nothing works, text still appears there
new Vue({
el: "#demo",
data() {
return {
isAdded: false
}
},
methods: {
add() {
this.isAdded = true
setTimeout(()=>{
this.isAdded = false
}, 2000);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<button #click="add">add</button>
<h1 v-if="isAdded">
added
</h1>
</div>
Related
I have a component in Nuxt with the following HTML in the template:
<div class="slider" id="slider" ref="slider" :style="'transform: transitionX(-' + sliderPosition + '%)'">
Then I also have a data variable:
export default {
data() {
return {
sliderPosition: 0
}
},
methods: {
moveLeft() {
this.sliderPosition -= 25
console.log(this.sliderPosition)
},
Now, every time I click the button that triggers the method, the console logs out the incremented sliderPosition value.
But in the template it always stays 0 and never updates - the transitionX is never changed (shows 0% in Chrome inspector and doesn't change).
Why could this be?
There is no transform function transitionX - docs. I guess you wanted translateX
Your sliderPosition is negative and you have a - in the style expression. So if the value of sliderPosition is -25 the style is translateX(--25) which is not valid
So just to be clear, this is not a problem of Vue not updating the DOM but instead problem of browser not accepting invalid style...
const vm = new Vue({
el: '#app',
data() {
return {
sliderPosition: 0
}
},
methods: {
move(percent) {
this.sliderPosition += percent
console.log(this.sliderPosition)
},
},
computed: {
sliderStyle() {
return {
transform: `translateX(${this.sliderPosition}%)`
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
<div id="app">
<button #click="move(-5)">Move left</button>
<button #click="move(5)">Move right</button>
<div class="slider" id="slider" ref="slider" :style="sliderStyle">This is OK!
</div>
<div class="slider" id="slider" ref="slider" :style="`transform: translateX(-${this.sliderPosition}%)`">This is not!
</div>
</div>
I need to do an action when Click Button (X) on search is clicked using Vue.
when he clicks on the input seach? on "x
new Vue({
el: "#app",
data: {
msg: 'the input is cleaned',
info:''
},
methods: {
handleClick: function(){
// to do sonthing when is cleaned not before
if(this.info=='')
alert(this.msg)
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="search" v-model="info" #click="handleClick" >
<br>
<span>{{ info }}</span>
</div>
You seem to want to differentiate between a normal click inside a input[type="search"] and a click on its clear control. I've spent some time trying to compare the two clicks and I wasn't able to find how they differ.
But I came up with a trick to figure it out:
if the input has a value (you need one for the clear button to be displayed)
we wait for DOM to update and, after it did, if the input no longer has a value (it was cleared) => bingo! it was a clear search click.
Therefore:
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
methods: {
handleClick(e) {
if (e.target.value) {
this.$nextTick() // wait for DOM update
.then(() => {
if (e.target.value === '') {
console.log('clear button clicked you must have, young Jedi!');
}
})
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="search" #click="handleClick">
</div>
However, I believe you're better off with a watch on your v-model:
watch: {
info(newVal, oldVal) {
if (oldVal && !newVal) {
console.log('info was cleared').
}
}
}
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
data: () => ({ info: '' }),
watch: {
info(newVal, oldVal) {
if (oldVal && !newVal) {
console.log('morning has broken...');
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="search" v-model="info">
</div>
It has the advantage it will not only trigger on click. It will trigger every time info changes from a truthy value to a falsy one, regardless of what caused the change (i.e: user selecting the text and pressing Delete or Backspace; any other component method clearing it, resetting the input or the parent form, etc...).
From the comment on the question, you're asking to call a function when the user clicks on the input field ? It's the way that I understood your question.
For that case, here is a quick demo on how to achieve that.
https://codesandbox.io/s/dry-lake-34bvi?file=/src/App.vue
I have some text:
Hover me
on positioning the cursor over the text, I would like it to change to:
I'm being hovered
on moving the cursor off, the text should change back to:
Hover me
I can do this with CSS, but I can't figure out how to do it with Vue?
Something like this should work.. easiest if you use a computed property.
CodePen mirror: https://codepen.io/oze4/pen/XQapNP
new Vue({
el: "#app",
data: {
hover: false
},
computed: {
message() {
return this.hover === true ? "I'm being hovered" : "Hover me";
}
},
methods: {
handleHover(s){
this.hover = s;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<div id="app">
<p #mouseover="handleHover(true)" #mouseleave="handleHover(false)">
{{ message }}
</p>
</div>
You need to define the output you want and a boolean for the hover state, I've called it "hoover"
data: () => ({
hoover: false
}),
computed: {
tyext() {
if (this.hoover === false) {
return "Hover Me"
}
return "I'm being hovered"
}
}
Then in the template you can have event listeners to change the boolean.
<p #mouseenter="hoover = true" #mouseleave="hoover = false">{{ tyext }}</p>
You typically wouldn't have logic like this in your template and would instead call a function like this #mouseenter="changeHoover" and change the state but I showed this for brevity, which was kind of pointless as I keep banging on like this.
I am trying to write a template that displays either Icon AAA or Icon BBB, depending on whether or not the item in the current iteration has a specific flag. Here is my code:
<div v-for="(item, itemIndex) in items">
<div v-if="item.hasUnreadComments">
<span>Display Icon AAA</span>
</div>
<div v-else>
<span>Display Icon BBB</span>
</div>
</div>
The issue here is that I need either icon displayed ONCE. If more than one item has it set to item.hasUnreadComments === true, Icon AAA will be displayed equally as many times, which is not what I want. Couldnt find anything in the docs and I dont want to bind it to a v-model.
Can this be done in Vue without a third data variable used as a flag?
You will have to do some sort of intermediate transformation. v-if is just a flexible, low-level directive that will hide or show an element based on a condition. It won't be able to deal directly with how you expect the data to come out.
If I'm understanding what you're asking for, you want an icon to only be visible once ever in a list. You can prefilter and use an extra "else" condition. This sounds like a use case for computed properties. You define a function that can provide a transformed version of data when you need it.
This example could be improved upon by finding a way to boil down the nested if/elses but I think this covers your use case right now:
const app = new Vue({
el: "#app",
data() {
return {
items: [{
hasUnreadComments: true
},
{
hasUnreadComments: true
},
{
hasUnreadComments: false
},
{
hasUnreadComments: true
},
{
hasUnreadComments: false
},
]
}
},
computed: {
filteredItems() {
let firstIconSeen = false;
let secondIconSeen = false;
return this.items.map(item => {
if (item.hasUnreadComments) {
if (!firstIconSeen) {
item.firstA = true;
firstIconSeen = true;
}
} else {
if (!secondIconSeen) {
item.firstB = true;
secondIconSeen = true;
}
secondIconSeen = true;
}
return item;
});
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(item, itemIndex) in filteredItems">
<div v-if="item.firstA">
<span>Display Icon AAA</span>
</div>
<div v-else-if="item.firstB">
<span>Display Icon BBB</span>
</div>
<div v-else>
<span>Display no icon</span>
</div>
</div>
</div>
I want to call a method when any anchor tag clicked. It is not possible to define #click or v-on on all element.
<a href="#">link1<a>
<a href="#">link2<a>
<a href="#">link3<a>
<a href="#">link4<a>
<a href="#">link5<a>
on jquery I can do this
$('a').click(function(){
//........
});
How can I achieve it in vuejs
Note: I have 10+ components in my app & a tag is spread every where in components.
You could attach the click handler on the parent/container element, and detect the target/child element being clicked via the event.target:
new Vue({
el: '#app',
methods: {
clicked(e) {
const container = e.currentTarget; // FYI
const anchor = e.target;
console.log(`${anchor.innerHTML} was clicked!`);
}
}
})
Vue.config.devtools = false;
Vue.config.productionTip = false;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="container" #click="clicked">
Link #1
Link #2
Link #3
<!-- more anchor elements here -->
</div>
</div>
This doesn't seem like a great idea, BUT you can "watch" changes. In this case to the collection of links and then attach an event handler...
Note: I didn't test this, but it should get you in the right direction
var vm = new Vue({
el: '#example',
data: {
linkList
},
// update the items in linkList when the DOM is ready
mounted(){
this.linkList = document.getElementsByTagName('a');
},
// watch for changes to linkList and do something
watch: {
linkList: function(){
for( var i=0; i < linkList.length; i ++ ){
LinkList[i].onclick = linkAction;
}
}
},
methods: {
linkAction: function (event) {
alert(event.target.tagName)
}
},
})
Edit: After reading the comments regarding the goal, you should let vue-router handle transitions between sections. I assume you don't want to edit each component so look into Dynamic Transitions inside the router.
In this case, you would "watch" for changes to the $route data and do your action there:
watch: {
'$route' (to, from) {
// to & from are data in the route object telling you which components are being shown
const toPath = to.path;
function(){
// do some action
}
}
}
This would function regardless of the tag used to trigger the route...
Well, you can achieve it by defining the links under data and loop through the v-for directive
First Way
new Vue({
el: "#app",
data: {
links: [
{ link: "first Link" },
{ link: "second Link" },
{ link: "Third Link" },
{ link: "Fourth Link" }
]
},
methods: {
onAnchor: function(e){
console.log("Clicked on", e.target.innerHTML);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Todos:</h2>
<p v-for="link in links">
{{link.link}}
</p>
</div>
Second way
Create a wrapper component for a and use the same throughout the application.
Vue.component('An', {
template: '#anchor',
props: ['link']
})
new Vue({
el: "#app",
data: function() {
return {
links: [
{ link: "first Link", text:'first Link' },
{ link: "second Link", text:'second Link' },
{ link: "Third Link", text:'third Link' },
{ link: "Fourth Link", text:'Fourth Link' }
]
}
},
methods: {
changeText(event) {
console.log(event)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Anchor</h2>
<p v-for="link in links">
<An :link="link" v-on:on-click="changeText($event)"></An>
</p>
</div>
<script type="text/x-template" id="anchor">
<p>
{{link.link}}
</p>
</script>
Hope this helps!