VueJs Like and Dislike buttons with Vfor - javascript

how to make the buttons increase separately?, I have tried similar solutions but they increase the number in the like and dislike together at the same time,
and I have this message in the console:
vue#next:1250 [Vue warn]: Property "counter" was accessed during render but is not defined on instance.
at
<div class="container">
<div class="comment--like--dislike--app">
<div
v-for="(comment, index) in comments" :key="index"
class="card mb-10 comment--item"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sint
deserunt, tempore accusamus iusto nobis dolore ratione itaque
perferendis delectus? Nostrum corporis, quod voluptates quis
consequuntur eveniet beatae dolor aperiam ad.
</p>
<div class="action--button--container text-right mt-10">
<button v-on:click="increment(index)" v-bind:id="comments.id" class="btn-sm btn-success">
Like ({{comments.counter}})
</button>
<button v-on:click="increment(index)" v-bind:id="comments.id" class="btn-sm btn-danger">
Dislike ({{comments.counter}})
</button>
</div>
</div>
this is the Vue code:
const app = Vue.createApp({
data() {
return {
comments: [{
id: 1,
counter:0
},
{
id: 2,
counter:0
},
],
};
},
methods: {
increment: function(index) {
this.comments[index].counter++;
},
},
}).mount(".container");

That's because you're using comments.counter instead of comment.counter (the comment at the current index in the array comments).
Change your markup to look like this:
<div class="container">
<div class="comment--like--dislike--app">
<div v-for="(comment, index) in comments" :key="index" class="card mb-10 comment--item">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sint
deserunt, tempore accusamus iusto nobis dolore ratione itaque
perferendis delectus? Nostrum corporis, quod voluptates quis
consequuntur eveniet beatae dolor aperiam ad.
</p>
<div class="action--button--container text-right mt-10">
<button v-on:click="increment(index)" v-bind:id="comment.id" class="btn-sm btn-success">
Like ({{comment.counter}})
</button>
<button v-on:click="increment(index)" v-bind:id="comment.id" class="btn-sm btn-danger">
Dislike ({{comment.counter}})
</button>
</div>
</div>
</div>
</div>
Additionally, as ashwin bande pointed out in the comments, you have a logic issue as well. You are using increment(index) for both your like and dislike buttons.
I believe what you're trying to accomplish is this:
const app = Vue.createApp({
data() {
return {
comments: [{
id: 1,
counter: {
likes: 0,
dislikes: 0
}
},
{
id: 2,
counter: {
likes: 0,
dislikes: 0
}
},
],
};
},
methods: {
increment(index) {
this.comments[index].counter.likes++;
},
decrement(index) {
this.comments[index].counter.dislikes++;
},
},
}).mount(".container");
<script src="https://unpkg.com/vue#next"></script>
<div class="container">
<div class="comment--like--dislike--app">
<div
v-for="(comment, index) in comments"
:key="index"
class="card mb-10 comment--item"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sint
deserunt, tempore accusamus iusto nobis dolore ratione itaque
perferendis delectus? Nostrum corporis, quod voluptates quis
consequuntur eveniet beatae dolor aperiam ad.
</p>
<div class="action--button--container text-right mt-10">
<button
#click="increment(index)"
:id="comment.id"
class="btn-sm btn-success"
>
Like ({{comment.counter.likes}})
</button>
<button
#click="decrement(index)"
:id="comment.id"
class="btn-sm btn-danger"
>
Dislike ({{comment.counter.dislikes}})
</button>
</div>
</div>
</div>
</div>

Related

Click duplicate button using JS

Im making a movie review page, i use a button to change the qualification.
How can i get the name of the movie when i press the button?
<div class="container-movies" id="container-movies">
<div class="movie">
<span class="text1" id="title">Transformers</span>
<p class="text2">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Labore soluta ullam officiis tempore sapiente, nesciunt veniam. Vitae explicabo labore soluta quis, omnis vero nulla, dignissimos necessitatibus repellat perferendis quisquam laboriosam.
</p>
<span class="text2">gen</span>
<div class="container-cal">
<span class="cal">4</span>
<button id="cal-btn">qualify</button>
</div>
</div>
<div class="movie">
<span class="text" id="title">movie title</span>
<p class="text2">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. At, sint fugit numquam dicta aperiam neque aliquam expedita ipsum sapiente assumenda rerum temporibus fuga similique sed, perspiciatis qui ipsa nihil adipisci.
</p>
<span class="text2">gen</span>
<div class="container-cal">
<span class="cal">4</span>
<button id="cal-btn">qualify</button>
</div>
</div>
This only sends me the name of the first node:
let cal = document.getElementById("cal-btn");
cal.addEventListener('click', getcal);
You can grab the constent of the id="title" and use it in the getcal function
const movieTitle = document.getElementById("title").innerText
document.getElementById("cal-btn"); will only return one element because ids are unique, you should use a class instead.
For each button, add a listener on click. Then because of the structure, search for the closest parent movie to find the title inside.
for (let btn of document.getElementsByClassName("cal-btn")) {
btn.addEventListener("click", () => {
console.log(btn.closest(".movie").querySelector(".title").textContent)
})
}
<div class="movie">
<span class="title">Transformers</span>
<button class="cal-btn">vote</button>
</div>
<div class="movie">
<span class="title">Another film</span>
<button class="cal-btn">vote</button>
</div>
You cant use the same id over and over again, in this case you should use a class or an custom attribute select all buttons and loop through them and call your function
let calBtns = document.querySelectorAll(".cal-btn");
calBtns.forEach(btn => {
btn.addEventListener('click', ()=>{
alert(btn.closest('.movie').querySelector('.title').innerText)
});
})
<div class="container-movies" id="container-movies">
<div class="movie">
<span class="text1 title">Transformers</span>
<p class="text2">Lorem ipsum</p>
<span class="text2">gen</span>
<div class="container-cal">
<span class="cal">4</span>
<button class="cal-btn">qualify</button>
</div>
</div>
<hr>
<div class="movie">
<span class="text title">movie title</span>
<p class="text2">Lorem, ipsum</p>
<span class="text2">gen</span>
<div class="container-cal">
<span class="cal">4</span>
<button class="cal-btn">qualify</button>
</div>
</div>

Trigger hover on flipbox when clicking on tab

I have a main section. Under the main section I have 2 columns, one with flipbox and other with tabs. I want to trigger hover on flip box when I clicked tab2. I don't have any clue about the JS but tried few of the fiddle's I found, the closet one to what I want is http://jsfiddle.net/EZ33Y/1/ but I was not able to get it working properly.
What I am trying to achieve is to display image related to tab for e.g Tab1 displays img1 and tab2 displays img2 or trigger hover when tab2 is selected so flip image displays tab2 img2
TIA
$(function(){
$('.tabs label').click(function(){
$('.images img').hide();
$('#tab'+($(this).parent('li').index()+1)+'-img').show();
});
});
/* HTML */
<div class="elementor-column elementor-col-33 elementor-top-column elementor-element elementor-element-fd8fa18" data-id="fd8fa18" data-element_type="column" id="tab1">
<div class="elementor-column-wrap elementor-element-populated">
<div class="elementor-widget-wrap">
<div class="elementor-element elementor-element-d5d5298 elementor-widget elementor-widget-eael-adv-tabs" data-id="d5d5298" data-element_type="widget" data-widget_type="eael-adv-tabs.default">
<div class="elementor-widget-container">
<div id="eael-advance-tabs-d5d5298" class="eael-advance-tabs eael-tabs-horizontal" data-tabid="d5d5298">
<div class="eael-tabs-nav">
<ul class="eael-tab-top-icon">
<li class="active">
<i class="fas fa-home"></i> <span class="eael-tab-title">Tab Title 1 </span>
</li>
<li class="inactive">
<i class="fas fa-home"></i> <span class="eael-tab-title">Tab Title 2</span>
</li>
</ul>
</div>
<div class="eael-tabs-content">
<div class="clearfix active">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Optio, neque qui velit. Magni dolorum quidem ipsam eligendi, totam, facilis laudantium cum accusamus ullam voluptatibus commodi numquam, error, est. Ea, consequatur. </div>
<div class="clearfix inactive">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Optio, neque qui velit. Magni dolorum quidem ipsam eligendi, totam, facilis laudantium cum accusamus ullam voluptatibus commodi numquam, error, est. Ea, consequatur. </div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

"else" is not working on my Jquery code with slideToggle

I have a section on my website, with Q/A blocks. If we click on question title (h3), it must appear answer hidden under the question.
So on the right side of question title, we have arrow down, and arrow up. As you might understand, it must be appeared arrow down when question is "closed", and arrow up when question is "open".
$("img.up").hide();
$(".question h3").click(function(){
var b = $(this);
var a = b.parent(".question").children(".answer");
a.slideToggle();
if(a.css('display') == 'block'){
b.children("img.down").hide();
b.children("img.up").show()
} else {
b.children("img.up").hide();
b.children("img.down").show()
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="question">
<h3>
А я могу ездить на Mercedes S-Class без прав?
<img src="img/icons/down.png" alt="" class="down">
<img src="img/icons/up.png" alt="" class="up">
</h3>
<div class="answer">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit aspernatur, consectetur amet mollitia quasi sint provident, totam ad facere quia cumque magnam quisquam culpa praesentium aperiam qui voluptatem maxime corporis.
</div>
</div>
Code works on first click, and ignores all next clicks. Else is not working. I know that it is easy but... Sometimes you can't do such a simple things
Try storing the state of .answer elements css display attribute, before calling the .slideToggle() method and use this stored state to hide/display your arrow images:
$("img.up").hide();
$(".question h3").click(function(){
var b = $(this);
var a = b.parent(".question").children(".answer");
// Store isVisible state for answer element before ..
var isVisible = a.css('display') == 'block';
// ..you call slideToggle()
a.slideToggle();
if(isVisible){
b.children("img.down").hide();
b.children("img.up").show()
} else {
b.children("img.up").hide();
b.children("img.down").show()
};
});
img {
width:1rem;
height:1rem;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="question">
<h3>
А я могу ездить на Mercedes S-Class без прав?
<img src="https://openclipart.org/image/2400px/svg_to_png/154963/1313159889.png" alt="" class="down">
<img src="https://openclipart.org/image/2400px/svg_to_png/154969/1313159942.png" alt="" class="up">
</h3>
<div class="answer">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit aspernatur, consectetur amet mollitia quasi sint provident, totam ad facere quia cumque magnam quisquam culpa praesentium aperiam qui voluptatem maxime corporis.
</div>
</div>
The reason for storing this is that slideToggle() will immediately sets the display of the answer to block, regardless of the animation (either to close, or open). For this reason, you need to determine if the answer is visible before animating the answer div (via the call to slideToggle()), so that you can use that state to control which up/down arrow is shown/hidden.
Here's an updated working jsFiddle for you to see :)
Here is the solution to your problem.
I have added
$('h3 img').toggle();
which will toggle the image accordingly.
Below is the working code.
$("img.down").hide();
$(".question h3").click(function(){
var b = $(this);
var a = b.parent(".question").children(".answer");
a.slideToggle();
$('h3 img').toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="question">
<h3>
А я могу ездить на Mercedes S-Class без прав?
<img src="img/icons/down.png" alt="down" class="down">
<img src="img/icons/up.png" alt="up" class="up">
</h3>
<div class="answer">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit aspernatur, consectetur amet mollitia quasi sint provident, totam ad facere quia cumque magnam quisquam culpa praesentium aperiam qui voluptatem maxime corporis.
</div>
</div>

I need to print divs and appending array contents inside of them in Javascript. How do i do that?

I have a div like this
<div id="news" class="col-sm-6 col-md-4 col-lg-4 pb-70">
<div class="post-prev-img">
<img src="images/blog/post-prev-1.jpg" alt="img">
</div>
<div class="post-prev-title">
<h3>TIME FOR MINIMALISM</h3>
</div>
<div class="post-prev-info">
JULE 10<span class="slash-divider">/</span>JOHN DOE
</div>
<div class="post-prev-text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Recusandae, nostrum, cumque culpa provident aliquam commodi assumenda laudantium magnam illo nostrum.
</div>
<div class="post-prev-more-cont clearfix">
<div class="post-prev-more left">
READ MORE
</div>
<div class="right" >
<span aria-hidden="true" class="icon_comment_alt"></span><span class="icon-count">21</span>
<span aria-hidden="true" class="icon_heart_alt"></span><span class="icon-count">53</span>
<a href="#" class="post-prev-count dropdown-toggle" data-toggle="dropdown" aria-expanded="false" >
<span aria-hidden="true" class="social_share"></span>
</a>
<ul class="social-menu dropdown-menu dropdown-menu-right" role="menu">
<li><span aria-hidden="true" class="social_facebook"></span>
</li>
<li><span aria-hidden="true" class="social_twitter"></span></li>
<li><span aria-hidden="true" class="social_dribbble"></span></li>
</ul>
</div>
</div>
</div>
I need this to be my "skeleton" for my other divs.
Now i want to make a for and append the content of my array inside of it and print every div inside an HTML page. How do i do that?
Thanks
You do this as follows,
make a template in your html and hide using css #template, make a div to show all the items that we are going to dynamically make #list
<div id="list">
</div>
<div id="template">
<div class="col-sm-6 col-md-4 col-lg-4 pb-70">
<div class="post-prev-img">
<img src="{{img}}" alt="img">
</div>
<div class="post-prev-title">
<h3>{{name}}</h3>
</div>
<div class="post-prev-info">
JULE 10<span class="slash-divider">/</span>JOHN DOE
</div>
<div class="post-prev-text">
{{info}}
</div>
<div class="post-prev-more-cont clearfix">
<div class="post-prev-more left">
READ MORE
</div>
<div class="right" >
<span aria-hidden="true" class="icon_comment_alt"></span><span class="icon-count">21</span>
<span aria-hidden="true" class="icon_heart_alt"></span><span class="icon-count">53</span>
<a href="#" class="post-prev-count dropdown-toggle" data-toggle="dropdown" aria-expanded="false" >
<span aria-hidden="true" class="social_share"></span>
</a>
<ul class="social-menu dropdown-menu dropdown-menu-right" role="menu">
<li><span aria-hidden="true" class="social_facebook"></span>
</li>
<li><span aria-hidden="true" class="social_twitter"></span></li>
<li><span aria-hidden="true" class="social_dribbble"></span></li>
</ul>
</div>
</div>
</div>
</div>
CSS to hide the template
#template {
display: none;
}
Then make an array of all your needed object data circle it with a loop and replace the data holders.
Then insert the new html into the dom
var assets= [
{
name: "Time for JS",
img: "http://via.placeholder.com/350x150",
link: "",
info:"Lorem ipsum dolor sit amet, consectetur adipisicing elit. Recusandae, nostrum, cumque culpa provident aliquam commodi assumenda laudantium magnam illo nostrum.",
},
{
name: "Time for CSS",
img: "http://via.placeholder.com/350x150",
link: "",
info:"ipsum dolor sit amet, consectetur adipisicing elit. Recusandae, nostrum, cumque culpa provident aliquam commodi assumenda laudantium magnam illo nostrum .consectetur adipisicing",
},
{
name: "Time for HTML",
img: "http://via.placeholder.com/350x150",
link: "",
info:"consectetur adipisicing consectetur adipisicing elit. Recusandae, nostrum, cumque culpa provident aliquam commodi assumenda laudantium magnam illo nostrum .consectetur adipisicing",
}
];
var html=""
assets.forEach(buildTemplate);
document.getElementById("list").innerHTML=html;
function buildTemplate(item) {
var template = document.getElementById("template").innerHTML;
template = template.replace("{{name}}", item.name);
template = template.replace("{{info}}", item.info);
template = template.replace("{{img}}", item.img);
html+=template;
}
Here it is in action, it's that simple no jquery ultra fast hardcode JS.
https://jsfiddle.net/5yeh38LL/
There is a much easier way use a js template engine there are lots on google but this demonstrates how this is done and how effectively a template system will work.
Try jQuery templates. You write your HTML code inside script tags and in your JS code you can call them and use them as you wish:
<script id="bookTemplate" type="text/x-jQuery-tmpl">
<div>
<img src="BookPictures/${picture}" alt="" />
<h2>${title}</h2>
price: ${formatPrice(price)}
</div>
</script>
Usage:
$("#bookTemplate").tmpl(books).appendTo("#bookContainer");

How to 'cut' DOM element and display it in other place? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have website, and I want to "cut" every div#id from .tab-content and add every div to every li only when viewport width is less than 768px.
My HTML page:
<section id="menu">
<div class="container">
<div class="row">
<div class="col-xs-12">
<ul id="menu-nav" class="nav nav-pills text-center">
<li class="active"><h2>About</h2></li>
<li><h2>Services</h2></li>
<li><h2>Contact</h2></li>
</ul>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="tab-content">
<div class="tab-pane active" id="about">
<div class="col-sm-8 col-sm-offset-2">
<p class="text-center">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis odit id praesentium, maxime, harum corporis officia laboriosam earum laudantium mollitia et quas, iure enim expedita. Nam sit, est libero obcaecati.
</p>
</div>
</div>
<div class="tab-pane" id="services">
<div class="col-sm-8 col-sm-offset-2">
<p class="text-center">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis odit id praesentium, maxime, harum corporis officia laboriosam earum laudantium mollitia et quas, iure enim expedita. Nam sit, est libero obcaecati.
</p>
</div>
</div>
<div class="tab-pane" id="contact">
<div class="col-sm-8 col-sm-offset-2">
<p class="text-center">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis odit id praesentium, maxime, harum corporis officia laboriosam earum laudantium mollitia et quas, iure enim expedita. Nam sit, est libero obcaecati.
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
I tried to use jquery for every div#ID, but it's not working.
$(document).ready(function(){
if ($(window).width() < 768) {
var divAbout = $('#about').pop();
$(divAbout).appendTo('#menu-nav li:first-of-type');
}
});
I want to have that result on mobile:
<li>
<h2>About</h2>
<div id="about">
...
</div>
</li>
And the same to other divs.
You can use the resize handler and do
var flag;
$(window).on('resize.menu', function () {
var width = $(window).width(),
$ul = $('#menu-nav');
if (width < 768 && flag != 1) {
flag = 1;
$('#menu .tab-content .tab-pane').each(function () {
$(this).appendTo($ul.find('li:has(a[href="#' + this.id + '"])'))
});
} else if (width >= 768 && flag != 2) {
flag = 2;
$ul.find('.tab-pane').appendTo('#menu .tab-content');
}
}).trigger('resize.menu')
Demo: Fiddle
Hope you're looking to develop a responsive web design. Instead of cutting the DOM and adding it to the li tag. Use CSS3 media queries to show and hide elements based on elements width.
But here is an approach for your question:
$(document).ready(function(){
if ($(window).width() < 768) {
$(".tab-content div").each(function(index, ele) {
var id = this.id; // about , contact
$("li a[href='#'"+id+"]").parent().parent().append(this);
// this will match li with a having href="#about" etc
});
}
});

Categories