vuejs - How to append html with click event - javascript

I try to append a couple of buttons with click event when the component is mounted:
data() {
return {
show_word: true,
game: {
//type: "memory, working memory",
type: 1,
name: "Symbols",
start:false,
total_combo:0,
total_correct:0,
total_incorrect:0,
total_correct_in_a_row:0,
max_correct_in_a_row:0,
correct_percent:0,
avg_time_for_ans:0,
button: '<button #click="checkNumbers">click</button>',
score_plus:0,
score_multi:0,
d_timer:600,
finish:false,
positive: null,
negative: null,
numbers_array:[],
abuse: {
clicks:5,
seconds:1,
max:3,
flag: false
}
},
}
},
methods:{
playGame(){
let tilesize = 50, tilecount = 6;
$( '#numbersContainer' ).empty()
let gRows = Math.floor($("#numbersContainer").innerWidth()/tilesize);
let gCols = Math.floor($('#numbersContainer').innerHeight()/tilesize);
let vals = _.shuffle(_.range(tilecount));
let xpos = _.shuffle(_.range(gRows));
let ypos = _.shuffle(_.range(gCols));
console.log(vals);
console.log(xpos);
console.log(ypos);
let $this = this;
_.each(vals, function(d,i){
var $newdiv = $('<button #click="checkNumbers('+(d+1)+')"/>').addClass("tile btn btn-info");
$this.game.numbers_array.push(d+1)
$newdiv.css({
'position':'absolute',
'left':(xpos[i] * tilesize)+'px',
'top':(ypos[i] * tilesize)+'px'
}).appendTo( '#numbersContainer' ).html(d+1);
});
},
checkNumbers($val){
console.log($val)
},
}
This is the html that i getting:
<div id="numbersContainer" class="col-ms-3">
<button #click="checkNumbers(6)" class="tile btn btn-info" style="position: absolute; left: 250px; top: 250px;">6</button>
<button #click="checkNumbers(5)" class="tile btn btn-info" style="position: absolute; left: 150px; top: 150px;">5</button>
<button #click="checkNumbers(1)" class="tile btn btn-info" style="position: absolute; left: 100px; top: 0px;">1</button>
<button #click="checkNumbers(3)" class="tile btn btn-info" style="position: absolute; left: 50px; top: 100px;">3</button>
<button #click="checkNumbers(2)" class="tile btn btn-info" style="position: absolute; left: 200px; top: 200px;">2</button>
<button #click="checkNumbers(4)" class="tile btn btn-info" style="position: absolute; left: 0px; top: 50px;">4</button>
</div>
The problems is that the "click" event is not working. Seems like the "checkNumbers" function is not register, although it registered in my methods.
What is the right way to append html element with register events?
Thank !

Don't manipulate the DOM directly, that's why you're using Vue in the first place. Use a combination of v-for and data() to manipulate state and have Vue populate the DOM.
Adding the #click="" within the direct DOM manipulation is going to cause the element to not be managed by Vue, in other words it won't have the Vue context.
const Game = {
props: ["tilecount"],
data() {
return {
tiles: []
};
},
mounted() {
this.tiles = _.shuffle(_.range(this.tilecount));
},
methods: {
checkNumbers(val) {
console.log(val);
}
}
};
const app = new Vue({
el: "#app",
components: {
game: Game
},
data() {
return {
tilecount: 50
};
}
});
.game .number-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.game .number-container button {
flex-basis: 20%;
height: 50px
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
<div id="app">
<game :tilecount="tilecount" inline-template>
<div class="game">
<div ref="numberContainer" class="number-container">
<button v-for="tile in tiles" #click="checkNumbers(tile)"> {{tile}}</button>
</div>
</div>
</game>
</div>

Related

how to add Add products on shopping cart without js framework

I am Beginner developer and I made e-commerce website (using html css and JavaScript(without framework)
I stuck in Add products on shopping cart because JavaScript and these my Code:
HTML:
<div class="small-container">
<div class="row">
<div class="col-4">
<img src="images/20 ps4.png" alt=""/></a>
<h4>20 Playstation Store(PSN)</h4>
<p>$20.00</p>
<button type="button" class="btn1" ><h3 class="text-btn">add to cart</h3></button>
</div>
<!--2-->
<div class="col-4">
<img src="images/25 ps4.png" alt="" />
<h4>25 Playstation Store(PSN)</h4>
<p>$25.00</p>
<button type="button" class="btn1" onclick="window.location.href='cart.html'"><h3 class="text-btn">add to cart</h3></button>
</div>
JavaScript:
function ready() {
var removeCartItemButtons = document.getElementsByClassName('btn1')
for (var i = 0; i < removeCartItemButtons.length; i++) {
var button = removeCartItemButtons[i]
button.addEventListener('click', removeCartItem)
}
var quantityInputs = document.getElementsByClassName('btn1')
for (var i = 0; i < quantityInputs.length; i++) {
var input = quantityInputs[i]
input.addEventListener('change', quantityChanged)
}
var addToCartButtons = document.getElementsByClassName('btn1')
for (var i = 0; i < addToCartButtons.length; i++) {
var button = addToCartButtons[i]
button.addEventListener('click', addToCartClicked)
}
document.getElementsByClassName('btn1')[0].addEventListener('click', purchaseClicked)
}
Css :
.row {
margin-top: 50px;
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: space-around;
}
.small-container{
max-width: 1080px;
margin: auto;
padding-left: 25px;
padding-right: 25px;
}
.col-4 {
flex-basis: 25%;
padding: 10px;
min-width: 200px;
margin-bottom: 50px;
transition: transform 0.5s;
}
.col-4 img {
width: 100%;
}
Thanks a lot.
I try to find function to add products item to the shopping cart
also i have to use JavaScript without framework
What's the purpose of var addToCartButtons = document.getElementsByClassName('btn1'), var quantityInputs = document.getElementsByClassName('btn1') and var removeCartItemButtons = document.getElementsByClassName('btn1')? The query is the same and therefore will always return identical elements.
Your approach is good, just add correct classes to your elements and queries. Be sure to make the HTML structure uniform. Metadata about your card can be stored in localStorage for example. You can learn about working with localStorage here. By the way, you can use newer syntax like forof loops or const keyword to make your code more readable.
(() => {
const addToCardButtons = document.querySelectorAll('.btn--add_to_cart');
for (const btn of addToCardButtons) {
const identifier = btn.dataset.target;
btn.addEventListener('click', () => addToCart(identifier))
}
const addToCart = (id) => {
console.log(id);
// handle 'add to cart' functionality
}
// other functionalities can follow the same structure
})()
<div class="small-container">
<div class="row">
<div class="col-4">
<img src="images/20 ps4.png" alt="" /></a>
<h4>20 Playstation Store(PSN)</h4>
<p>$20.00</p>
<button type="button" data-target="1" class="btn btn--add_to_cart">add to cart</button>
</div>
<!--2-->
<div class="col-4">
<img src="images/25 ps4.png" alt="" />
<h4>25 Playstation Store(PSN)</h4>
<p>$25.00</p>
<button type="button" data-target="2" class="btn btn--add_to_cart">add to cart</button>
</div>

Hide a dropdown on click

I would like to hide a dropdown after I select something from it, but keep it there for me to hover over again later.
My current code:
<div class="navbutton_container">
<button onclick="someFunction()"><p>Title</p></button>
<div class="nav_dropdown">
<button onclick="someFunction()"><p>Content1</p></button>
<button onclick="someFunction()"><p>Content2</p></button>
<button onclick="someFunction()"><p>Content3</p></button>
<button onclick="someFunction()"><p>Content4</p></button>
</div>
</div>
.navbutton_container > .nav_dropdown {
display: none;
opacity: 0;
}
.navbutton_container:hover > .nav_dropdown {
display: block;
opacity: 1;
position: absolute;
}
After I select any button in this, I would like the dropdown to temporarily disappear so it's out of the way until they stop hovering over it. After they move off, I would like it so they could move back on and have the :hover property to work again.
If you think there's a better structure, I'm 100% open to changing it!
Here's a method that will use a combination of adding classes and detecting mouseouts to acheive the goal
function someFunction() {}
window.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.navbutton_container').forEach(el => el.addEventListener('mouseover', e => {
let targ = e.target.classList.contains('navbutton_container') ? e.target : e.target.closest('.navbutton_container');
targ.querySelector('.nav_dropdown').classList.remove('hold');
}))
document.addEventListener('click', e => {
if (e.target.closest('.nav_dropdown')) {
e.target.closest('.nav_dropdown').classList.add('hold')
}
})
})
.navbutton_container>.nav_dropdown {
display: none;
opacity: 0;
}
.navbutton_container:hover>.nav_dropdown {
display: block;
opacity: 1;
position: absolute;
}
.navbutton_container:hover>.nav_dropdown.hold {
display: none;
opacity: 0;
}
<div class="navbutton_container">
<button onclick="someFunction()" class='toggler'><p>Title</p></button>
<div class="nav_dropdown ">
<button onclick="someFunction()"><p>Content1</p></button>
<button onclick="someFunction()"><p>Content2</p></button>
<button onclick="someFunction()"><p>Content3</p></button>
<button onclick="someFunction()"><p>Content4</p></button>
</div>
</div>
<div class="navbutton_container" style='margin-top:100px'>
<button onclick="someFunction()" class='toggler'><p>Title</p></button>
<div class="nav_dropdown ">
<button onclick="someFunction()"><p>Content1</p></button>
<button onclick="someFunction()"><p>Content2</p></button>
<button onclick="someFunction()"><p>Content3</p></button>
<button onclick="someFunction()"><p>Content4</p></button>
</div>
</div>

Vue: How do I generate a new instance of a div with a buttonclick?

I need to create a function that generates a new instance of a specific div (.container in the template) when a button (#addDiv) is clicked. The button should be the only thing visible on the webpage before that. How do I do?
I know that it may be possible to do this with document.appendChild. Is there a better way?
I am using toggle-function that works great, I have included it in the code to give you the whole picture.
Vue
Vue.component('dynamicdDvs', {
template: `
<div>
<div class="headerDiv">
<button class="addDiv" type="button" v-on:click="createDiv">Create</button>
</div>
<div class="container">
<div class="createdDiv">
<h2>I am dynamic!</h2>
<button class="minimize" v-on:click="expand">Make me smal</button>
</div>
<div class="createdDivMinimized" v-if="!displayDiv">
<p>I am a smal version of the created div!</p>
<button class="maximize" v-on:click="expand">Expand me</button>
</div>
</div>
</div>
`,
data:function () {
return {
displayDiv: false
}
},
methods: {
expand: function () {
this.displayDiv = !this.displayDiv;
},
createDiv: function() {
//The function that creates a new div, with the same code as
//.createdDiv and .createDivMinimized may be placed here
}
}
});
CSS
.headerDiv {
height: 100px;
width: 400px;
background-color: blue;
color: white
}
.createdDiv {
height: 300px;
width: 400px;
background-color: black;
color: white
}
.createdDivMinimized {
height: 300px;
width: 400px;
background-color: red;
color: white
}
HTML
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="parent">
<dynamicDivs></dynamicDivs>
</div>
So what you can do is set a number in data for the number of <div> elements and use v-for with a range. For example
data () {
return {
displayDiv: [false],
divs: 1
}
}
And in your template
<template v-for="n in divs">
<div class="createdDiv">
<!-- snip -->
<button class="minimize" v-on:click="displayDiv[n-1] = !displayDiv[n-1]">Make me small</button>
</div>
<div class="createdDivMinimized" v-if="!displayDiv[n-1]">
<!-- snip -->
</div>
</template>
and in your methods...
createDiv () {
this.divs++
this.displayDiv.push(false)
}

Vue.js: Collapse/expand all elements from parent

I need to add "expand/collapse all" functionality for my Vue component(some collapsible panel).
If user clicks collapse button then clicks on some panel and expand it then clicking on collapse button will do nothing because watched parameter will not change.
So how to implement this functionality properly (buttons must collapse and expand components always)?
I prepared simple example(sorry for bad formatting, it looks nice in editor :( ):
var collapsible = {
template: "#collapsible",
props: ["collapseAll"],
data: function () {
return {
collapsed: true
}
},
watch: {
collapseAll: function(value) {
this.collapsed = value
}
}
}
var app = new Vue({
template: "#app",
el: "#foo",
data: {
collapseAll: true
},
components: {
collapsible: collapsible
}
});
.wrapper {
width: 100%;
}
.wrapper + .wrapper {
margin-top: 10px;
}
.header {
height: 20px;
width: 100%;
background: #ccc;
}
.collapsible {
height: 100px;
width: 100%;
background: #aaa;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id="foo"></div>
<script type="text/x-template" id="collapsible">
<div class="wrapper">
<div class="header" v-on:click="collapsed = !collapsed"></div>
<div class="collapsible" v-show="!collapsed"></div>
</div>
</script>
<script type="text/x-template" id="app">
<div>
<button v-on:click="collapseAll = true">Collapse All</button>
<button v-on:click="collapseAll = false">Expand All</button>
<collapsible v-for="a in 10" v-bind:collapseAll="collapseAll" v-bind:key="a"></collapsible>
</div>
</script>
Thanks!
This is a case where I might use a ref.
<button v-on:click="collapseAll">Collapse All</button>
<button v-on:click="expandAll">Expand All</button>
<collapsible ref="collapsible" v-for="a in 10" v-bind:key="a"></collapsible>
And add methods to your Vue.
var app = new Vue({
template: "#app",
el: "#foo",
methods:{
collapseAll(){
this.$refs.collapsible.map(c => c.collapsed = true)
},
expandAll(){
this.$refs.collapsible.map(c => c.collapsed = false)
}
},
components: {
collapsible: collapsible
}
});
Example.

How to slide out and slide in two divs alternately in single line?

I'm trying to do function to sliding new added content, using jQuery slide effect but I can't apply any solutions to put two divs in a single line. How to fix code below to slide from left to the right side by side? Maybe this code is completely to rebuild?
jsFiddle:
jsfiddle
JS:
$(function() {
$("#hello").html("Hello");
$('#edit').toggle(function() {
var newhtml = '<input type="text" id="hello_input" value="" />';
slideNewContent(newhtml);
}, function() {
var newhtml = $("#hello_input").val();
slideNewContent(newhtml);
});
});
function slideNewContent(c) {
$("#slideOut").empty();
$("#slideIn").children().clone().appendTo("#slideOut");
$("#slideIn").find("#hello").html(c);
var slideOut = $("#slideOut");
var slideIn = $("#slideIn");
slideOutIn(slideOut, slideIn);
}
function slideOutIn(outElement, inElement) {
var hideoptions = { "direction": "right", "mode": "hide" };
var showoptions = { "direction": "left", "mode": "show" };
$(outElement).effect("slide", hideoptions, 1000);
$(inElement).effect("slide", showoptions, 1000);
}
​HTML:
<div class="span3">
<div id="slider">
<div id="slideIn" class="content">
<span>
<span id="hello"></span>
<button class="btn btn-mini" id="edit">Edit</button>
</span>
</div>
<div id="slideOut" class="content"></div>
</div>
</div>​
CSS:
#slider {
/*float:left;*/
display: inline-block;
}
#slideIn {
width: 270px;
/*display: inline;*/
}
#slideOut {
width: 270px;
/*display: inline;*/
}
#hello_input {
width:160px;
}
Edit to this
$(outElement).effect("slide", hideoptions, 0);
$(inElement).effect("slide", showoptions, 0);

Categories