dynamic form funky behavior in vuejs - javascript

I am using VueJS 2.6.11 and bootstrap 4 to create two dynamic sections(Category and Product) that contain divs and input fields. The product section is nested within the category section. When someone clicks the New Category button another category should get generated. The same behavior should also happen when someone clicks the New Product button, another Product section should get generated, but only inside the current category section.
Issue:
When someone clicks the New Product button, the Add Product section will get generated inside all current Category sections. Also, v-model appears to bind to every product name input. When someone clicks the X button for a specific Product section one product section would get deleted from all current Category sections.
I'm not exactly sure why this is happening.
codepen:
https://codepen.io/d0773d/pen/ExjbEpy
code:
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Create Categories and Products</title>
<!-- New Category -->
<button class="btn btn-success mt-5 mb-5"
#click="addNewCategoryForm">
New Category
</button>
<div class="card mb-3" v-for="(category, index) in categories">
<div class="card-body">
<span class="float-right"
style="cursor:pointer"
#click="deleteCategoryForm">
X
</span>
<h4 class="card-title">Add Category</h4>
<div class="category-form">
<input
type="text"
class="form-control mb-2"
placeholder="Category Name"
v-model="category.name">
</div>
<!-- New Product -->
<button class="btn btn-success mt-5 mb-5"
#click="addNewProductForm">
New Product
</button>
<div class="card mb-3" v-for="(product, index) in products">
<div class="card-body">
<span class="float-right"
style="cursor:pointer"
#click="deleteProductForm">
X
</span>
<h4 class="card-title">Add Product</h4>
<div class="product-form">
<input
type="text"
class="form-control mb-2"
placeholder="Product Name"
v-model="product.name">
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '.container',
data: {
categories: [
{
name: '',
}
],
products: [
{
name: '',
}
]
},
methods: {
addNewCategoryForm () {
this.categories.push({
name: '',
});
},
deleteCategoryForm (index) {
this.categories.splice(index, 1);
},
addNewProductForm () {
this.products.push({
name: '',
});
},
deleteProductForm (index) {
this.products.splice(index, 1);
},
}
});
</script>

The general problem is you don't specify which products belong to which category. So in your current code, all products belong to all categories.
I would suggest to instead nest the products inside the category object.
var app = new Vue({
el: ".container",
data: {
categories: [{
name: "",
products: [{
name: ""
}]
}]
},
methods: {
addNewCategoryForm() {
this.categories.push({
name: "",
products: []
});
},
deleteCategoryForm(index) {
this.categories.splice(index, 1);
},
addNewProductForm(index) {
this.categories[index].products.push({
name: ""
});
},
deleteProductForm(categoryIndex, index) {
this.categories[categoryIndex].products.splice(index, 1);
}
}
});
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://unpkg.com/bootstrap#4.4.1/dist/css/bootstrap.min.css">
<!-- Vue -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Create Categories and Products</title>
<div class="container">
<!-- New Category -->
<button class="btn btn-success mt-5 mb-5" #click="addNewCategoryForm">
New Category
</button>
<div class="card mb-3" v-for="(category, catIndex) in categories">
<div class="card-body">
<span class="float-right" style="cursor:pointer" #click="deleteCategoryForm">
X
</span>
<h4 class="card-title">Add Category</h4>
<div class="category-form">
<input type="text" class="form-control mb-2" placeholder="Category Name" v-model="category.name">
</div>
<!-- New Product -->
<button class="btn btn-success mt-5 mb-5" #click="addNewProductForm(catIndex)">
New Product
</button>
<div class="card mb-3" v-for="(product, index) in category.products">
<div class="card-body">
<span class="float-right" style="cursor:pointer" #click="deleteProductForm(catIndex, index)">
X
</span>
<h4 class="card-title">Add Product</h4>
<div class="product-form">
<input type="text" class="form-control mb-2" placeholder="Product Name" v-model="product.name">
</div>
</div>
</div>
</div>
</div>
</div>

Related

Input variable is visible, but not accessable after Ajax , $each and Div clone process

I was taken to the town square and stoned for my last posting about this for errors in my example code...haha. It due to stressing over this. I had to delete it in the end. Thanks for the rebuke guys it helps newbies like me learn. Now I learnt from that and presented it all in a code run.
My issue is The registration expire date is visible but when I click my test date input button it shows as empty. I created a Code run/ Snippet that replicates the issue.
**Important.**
Please remember to disable the variable carDetailCloned.find('.mydate').val(person.registration);
using // before enabling the test variables.
card-container is after the div/card had been cloned. I put the same mydate variable or one of the same variations of the same variable for testing below this.
$('.card-container').append(carDetailCloned);
Results from variations below:
Data visible but Blank Alert so no difference.
//carDetailCloned.find('.mydate').val(person.registration);
Data visible,data found as it Alerts the visible data!, But the same date shows on all fields.
//$('.card').find('.mydate').val(person.registration);
The end game
I need to use that value in another script, but I can't select it.
$(document).ready(function(){
//simulates jason data result from Ajax
var data = [
{id:31,name:"Mike",surname:"Rynes",registration:1980},
{id:32,name:"James",surname:"Bond",registration:2000},
{id:33,name:"Helen",surname:"Wright",registration:1978},
];
$.each(data, function( i, person ) {
var carDetailCloned = $('.card').first().clone().show();
carDetailCloned.find('.id').text(person.id);
carDetailCloned.find('.name').text(person.name);
carDetailCloned.find('.surname').text(person.surname);
carDetailCloned.find('.mydate').val(person.registration);
$('.card-container').append(carDetailCloned);
//Remove Slashes below to test variations. One at a time please and make sure you disable the one above the card container first thanks.
//carDetailCloned.find('.mydate').val(person.registration);
//$('.card').find('.mydate').val(person.registration);
//$("#"+id).find('.mydate').val(person.registration);
});
});
$(document).ready(function(){
$(document).on('click', '.card .test-btn', function(event){
var mydate = $('.card').find('.mydate').val();
alert(mydate);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<div class="album py-1">
<div class="container bg-light">
<div class="row py-2">
<div class="col-md-3 card-container" >
<div class="card mb-3 shadow-sm" style="display:none;">
<div class="hover-container">
</div>
<div class="card-body CarDetail">
<p class="card-text font-weight-bold">ID:
<span class="id"></span>
</p>
<p class="card-text font-weight-bold">Name:
<span class="name"></span>
</p>
<p class="card-text font-weight-bold">Surname:
<span class=" surname"></span>
</p>
<div class="d-flex justify-content-between align-items-center">
<p class="font-weight-bold ">Registration:
<span class="font-weight-plain"></span>
<span class="registration"></span> <span>Expires:
<input type="text" class="mydate" name="" value=""> </span>
</p>
</div>
<p><button class="test-btn" >Test mydate input</button> </p>
</div>
</div>
</div>
</div>
</div>
</div>
You can use .closest() to get closest card div where button is clicked then use .find() to find your input and show same.
Demo Code :
$(document).ready(function() {
//simulates jason data result from Ajax
var data = [
{
id: 31,
name: "Mike",
surname: "Rynes",
registration: 1980
},
{
id: 32,
name: "James",
surname: "Bond",
registration: 2000
},
{
id: 33,
name: "Helen",
surname: "Wright",
registration: 1978
},
];
$.each(data, function(i, person) {
var carDetailCloned = $('.card').first().clone().show();
carDetailCloned.find('.id').text(person.id);
carDetailCloned.find('.name').text(person.name);
carDetailCloned.find('.surname').text(person.surname);
carDetailCloned.find('.mydate').val(person.registration);
$('.card-container').append(carDetailCloned);
});
});
$(document).ready(function() {
$(document).on('click', '.card .test-btn', function(event) {
//use closest and find
var mydate = $(this).closest('.card').find('.mydate').val();
alert(mydate);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<div class="album py-1">
<div class="container bg-light">
<div class="row py-2">
<div class="col-md-3 card-container">
<div class="card mb-3 shadow-sm" style="display:none;">
<div class="hover-container">
</div>
<div class="card-body CarDetail">
<p class="card-text font-weight-bold">ID:
<span class="id"></span>
</p>
<p class="card-text font-weight-bold">Name:
<span class="name"></span>
</p>
<p class="card-text font-weight-bold">Surname:
<span class=" surname"></span>
</p>
<div class="d-flex justify-content-between align-items-center">
<p class="font-weight-bold ">Registration:
<span class="font-weight-plain"></span>
<span class="registration"></span> <span>Expires:
<input type="text" class="mydate" name="" value=""> </span>
</p>
</div>
<p><button class="test-btn">Test mydate input</button> </p>
</div>
</div>
</div>
</div>
</div>
</div>

Creating a search box with vue.js

I'm wanting to add functionality for the search box to search the current cards on the page for the movie inputted, but all the other examples and solutions I've found online their solutions don't seem to work for me.
This is the body of the HTML:
<body>
<div id="app">
<div class="row pt-3">
<div class="col">
<input type="text" class="form-control" v-model="search" placeholder="Search Movies">
</div>
<div class="col-md-auto">
<button type="button" class="btn btn-primary" id="search"> Go! </button>
</div>
</div>
<div class="row text-center pt-3">
<div v-for="movie in movies" class="card" style="width: 18rem;">
<img :src="movie.Poster" class="card-img-top" alt="img">
<div class="card-body">
<h5 class="card-title">{{ movie.Title }}</h5>
<p class="card-text">{{ movie.Year }}</p>
View Movie
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="main.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
</body>
And this the JS file:
new Vue({
el: '#app',
data: {
movies: [],
search: '',
},
created() {
var vm = this
axios.get('https://www.omdbapi.com/?s=Harry+Potter&apikey=a9018efb')
.then(function(response) {
vm.movies = response.data.Search
})
}
})
Instead of looping over movies, create a computed set of filtered data to loop over. For example, if you were searching the titles:
computed: {
searchedMovies() {
return this.movies.filter(movie => {
return movie.Title.toLowerCase().includes(this.search.toLowerCase());
})
}
}
Loop over this:
<div v-for="movie in searchedMovies" :key="movie.Title">
...
</div>
When you haven't searched for anything, this will return all movies.

how can I make an v-if depending on a boolean object property?

I have a array of objects(comments from posts kind like facebook comments or any other social network) and I iterate it with an v-for, then I have on each comment a dropdown button with "edit" and "delete" buttons, I would like that when I press the edit button the comment would change to an input so I can edit it, so I added a property click_to_edit initialize in false to each comment object, so when I click on edit it changes the condition that the v-for is related to. But it does not change it, I guess it is that as the property is inside an object it always return false and therefore the condition never changes, but I do not know how else do this. This is the html for the v-for:
<div
class="mb-2"
v-bind:class="'comment_'+post.id"
v-for="(comment, index) in comments"
:key="index"
v-if="comment.id_post === post.id"
>
<div class="row">
<div class="col-img-user-post text-center">
<img
class="rounded-circle img-icon-profile"
:src="routes.user_files+'/'+comment.code+'/'+comment.picture"
alt
/>
</div>
<div class="col">
<div class="row">
<div class="col">
<div class="card-comment">
<div class="row">
<div v-if="!comment.clicked_to_edit" class="col">
<p class="mt-2 mb-2">{{ comment.description }}</p>
<p class="mb-0 font-smaller grey-color">{{ comment.time_ago }}</p>
</div>
<div v-if="comment.clicked_to_edit" class="col">
<input v-model="comment.description" type="text" />
<p class="mb-0 font-smaller grey-color">{{ comment.time_ago }}</p>
</div>
<div class="col-1">
<div class="row dropdown">
<div class="col">
<a
class="font-smaller"
type="button"
:id="'dropdownMenuButtonComment_'+index"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<i class="fas fa-lg fa-angle-down grey-color"></i>
</a>
<div
class="dropdown-menu dropdown-menu-right"
:aria-labelledby="'dropdownMenuButtonComment_'+index"
>
<button
class="dropdown-item"
v-if="comment.id_user===profile_info.id_user"
#click="editComment(comment.id, index)"
>
<i class="far fa-edit"></i>
Edit
</button>
<button
class="dropdown-item"
data-toggle="modal"
data-target="#modalDeleteComment"
v-if="comment.id_user===profile_info.id_user"
#click="actionComment(comment.id, 2, index)"
>
<i class="far fa-trash-alt red-color"></i>
<span class="red-color">Delete</span>
</button>
<button
class="dropdown-item"
v-if="comment.id_user!==profile_info.id_user"
#click="actionComment(comment.id, 3)"
>
<i class="far fa-flag"></i>
Report
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
The object comment stated in the data:
comment: {
id: "",
id_post: "",
description: "",
clicked_to_edit: false,
id_user: this.profile_info.id_user,
code: this.profile_info.code,
name: this.profile_info.name,
surname_1: this.profile_info.surname_1,
surname_2: this.profile_info.surname_2,
nick: this.profile_info.nick,
picture: this.profile_info.picture,
role: this.profile_info.id_role,
time_ago: "0 minutes"
},
and the edit function:
editComment(id, index) {
this.comments[index].clicked_to_edit = true;
console.log(this.comments[index]);
},
I purposefully ignored your model, to show a general case. If you need help applying it to your case, let me know.
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
data: () => ({
comments: [
{ id: 'one', description: "test 1" },
{ id: 'two', description: "test 2" },
{ id: 'three', description: "test 3" }
].map(i => ({ ...i,
isEditing: false
}))
}),
methods: {
async toggleEditing(comment, index) {
const isOpening = !comment.isEditing;
this.comments
.filter(c => c.isEditing)
.forEach(c => c.isEditing = false);
if (isOpening) {
comment.isEditing = true;
await this.$nextTick();
this.$refs.comments[index].querySelector('input').focus()
}
},
blur: ev => ev.target.blur()
}
})
.comment {
min-height: 21px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(comment, i) in comments" ref="comments" :key="comment.id">
<div v-if="!comment.isEditing"
v-text="comment.description"
class="comment"
#click="toggleEditing(comment, i)"></div>
<div v-else>
<input v-model="comment.description"
#blur="toggleEditing(comment)"
#keyup.enter="blur"
/>
</div>
</div>
</div>

Bootstrap modal window won't open because of interference with other elements

I can't seem to figure out why bootstrap's modal window isn't popping up.
I've looking into other similar questions and I still can't get it to work.
I've tried the process of elimination and try to eliminate all my scripts (except the bootstrap script) and it still won't open. Same with my CSS files. I also had inputted manual code for a modal window (before I incorporated bootstrap) so I was worried that the id="modal" from other modals would interfere. I deleted those too and nothing worked.
Here is my codepen, I've commented the sections the modal window code starts: https://codepen.io/eylenkim/pen/KKwMPLm
HTML:
<!--
-- fix other <a> tags // fix navigation
--fix "exit" for contact pop up (mobile)
-- center the Contact dialog box on viewport in mobile
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Art By Eylen | Shop</title>
<meta name="description" content="Browse Eylen's art portfolio to view work created with 35mm photography, blockprinting, and acrylic.">
<meta name="author" content="Eylen Kim">
<!-- data-src
––––––––––––––––––––––––––––––––––––––––––––––––––- -->
<link href="subpage-stylesheet.css" rel=stylesheet type="text/css">
<link href="StyleSheet.css" rel=stylesheet type="text/css">
<link href="skeleton.css" rel=stylesheet type="text/css">
<link href="otherCss/normalize.css" rel="stylesheet" type="text/css">
<link href="otherCss/font-awesome.css" rel=stylesheet type="text/css">
<link href="bootstrap-4.3.1-dist/css/bootstrap.css" rel=stylesheet type="text/css">
<link href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet" type="text/css">
<!-- Mobile Meta
––––––––––––––––––––––––––––––––––––––––––––––––––-->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<!-- Favicon
––––––––––––––––––––––––––––––––––––––––––––––––––-->
<link rel="icon" type="image/png" href="photo/favicon1.png" />
</head>
<!-- Menu // Hamburger Bar
––––––––––––––––––––––––––––––––––––––––––––––––––-->
<nav class="navigation">
<a href="#" class="menu-icon">
<i class="fa fa-bars"></i>
</a>
<ul class="main-navigation" role="navigation">
<div id="nav-x" class="menu-icon">&Cross;</div>
<li>
<div href="index.html">
Home</a>
</li>
<li>
<div href="portfolio.html">
Portfolio</a>
</li>
<li>
<div class="trigger" style="height: 100%;padding: 10px 0 10px 10px;">
About Me
<div class="modal">
<div class="modal-content" style="height: 95%; max-height: 600px;padding: 2rem 4.6rem;">
<span class="close-button">×</span>
<h3>
Hello,<br>I'm Eylen!
</h3>
<img id="about-me-pic" src="photo/meee.JPG">
<p style="font-size: .75em; height: 44.3%; padding-top: 15px;">This art website is my passion project. I have coded my own platform to showcase & sell my art. What a treat to have you here on this site!<br><br> The mediums I work with: 35mm film photography, acrylic (canvas & glass), polymer clay (earrings), and printmaking.
<br><br>
In my free time I like petting my cat, tickling some gnarly tunes on the bass/electric guitar, coding, playing video games, and doing art stuff.<br><br>
</p>
</div>
</div>
</div>
</li>
<li style="height: 100%;padding: 20px 0 10px 7px;">
<p class="about-me-desktop" onclick="document.getElementById('id01').style.display='block'" style="position: relative;top: -3px;">Contact
</p>
<div class="w3-container">
<div id="id01" class="w3-modal">
<div class="modal-content-contact-portfolio">
<span class="close-button" onclick="document.getElementById('id01').style.display='none'" >×</span>
<h3 style="margin-bottom: 0px;">
Contact Me
</h3>
<p>
<div class="contact-us-form" style="font-size: .7em;">
<form action="https://formspree.io/eylenkim#gmail.com" method="POST">
<div class="row" style="z-index: 9999999;">
<div class="six columns">
<input class="u-full-width" type="text" placeholder="Name" id="nameInput" name="Name" requiprintmaking>
</div>
<div class="six columns">
<input class="u-full-width" type="email" placeholder="Email" id="emailInput" name="Email" requiprintmaking>
</div>
</div>
<textarea class="u-full-width" placeholder="Message" id="messageInput" name="Message" requiprintmaking style="height: 160px;margin-top: 20px;line-height: 17px;padding-top: 8px;"></textarea>
<input class="button u-pull-right" type="submit" value="Send" style="color: black;"><br><br><br>
</form>
</div>
</p>
</div>
</div>
</div>
</li>
</ul>
</nav>
<header>
<div class="container fade-in">
<div class="row">
<a href="index.html">
<h1 class="one-third column u-pull-left">Art By <span><br></span><span id="h1-title-span"> Eylen</span></h1>
</a>
<h2 class="one-third column u-pull-left" id="portfolio-title-desktop">| Shop</h2>
<h2 class="one-third column u-pull-left" id="portfolio-title-mobile">
<span>&boxh;&boxh;<br></span>Shop
</h2>
<div class="about-contact-text" class="one-third column u-pull-right">
<a href="index.html">
<p class="about-me-desktop">Home</p>
</a>
<span class="trigger">
<p class="about-me-desktop">
About Me
</p>
<div class="modal">
<div class="modal-content">
<span class="close-button">×</span>
<h3>
Hello,<br>I'm Eylen!
</h3>
<img id="about-me-pic" src="photo/meee.JPG">
<p>This art website is my passion project. I have coded my own platform to showcase & sell my art. What a treat to have you here on this site!<br><br> The mediums I work with: 35mm film photography, acrylic (canvas & glass), polymer clay (earrings), and printmaking.
<br><br>
In my free time I like petting my cat, tickling some gnarly tunes on the bass/electric guitar, coding, playing video games, and doing art stuff.<br><br>
</p>
</div>
</div>
</span>
<p class="about-me-desktop" onclick="document.getElementById('id02').style.display='block'">
Contact
</p>
<div class="w3-container">
<div id="id02" class="w3-modal">
<div class="modal-content-contact">
<span class="close-button" onclick="document.getElementById('id02').style.display='none'" >×</span>
<h3 style="margin-bottom: 0px;">
Contact Me
</h3>
<p>
<div class="contact-us-form">
<form action="https://formspree.io/eylenkim#gmail.com" method="POST">
<div class="overlap-text">
<div class="overlap-text-base-contact">
<h2 class="load two-thirds column">Contact</h2>
</div>
</div>
<div class="row" style="z-index: 9999999;">
<div class="six columns">
<input class="u-full-width" type="text" placeholder="Name" id="nameInput" name="Name" required>
</div>
<div class="six columns">
<input class="u-full-width" type="email" placeholder="Email" id="emailInput" name="Email" required>
</div>
</div>
<br>
<textarea class="u-full-width" placeholder="Message" id="messageInput" name="Message" required style=" height: 100px;
margin-top: 10px;
line-height: 17px;
padding-top: 8px;"></textarea>
<br><br>
<input class="button u-pull-right" type="submit" value="Send"><br><br><br>
</form>
</div>
</p>
</div>
</div>
</div>
</div>
</div>
</header>
<body class="top" id="top">
<section class="grid-wrapper">
<div class="filter-controls">
<div class="control fade-in">Filter By:
<select class="filter-field form-control">
<option value="">None</option>
<option value="prints">Prints</option>
<option value="earrings">Earrings</option>
<option value="commissions">Commisions</option>
</select>
</div>
</div>
<div class="grid bootstrap-on fade-in" style="flex-direction: row !important;">
<!------ Product w/ Carousel ---------------------------------------------------------------------->
<div class="card item" data-color="earrings">
<div class="price-tag">$10</div>
<div id="earrings1" class="carousel slide" data-interval="false">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="image" class="d-block w-100 crop-shp" alt="...">
</div>
<div class="carousel-item">
<img src="image" class="d-block w-100 crop-shop" alt="...">
</div>
</div>
<a class="carousel-control-prev" href="#earrings1" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#earrings1" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
<div class="card-body">
<h5 class="card-title">Carousel</h5>
<p class="card-text">I want to potentially add the ability to click on the carousel images for the pop up modal</p>
</div>
</div>
<!------ Product w/ Modal Window ---------------------------------------------------------------------->
<div class="card item" data-color="prints">
<div class="price-tag" data-toggle="modal" data-target="#exampleModal">$10</div>
<img src="image" class="card-img-top crop-shop" alt="Print" data-toggle="modal" data-target="#exampleModal">
<div class="card-body">
<h5 class="card-title">(Modal Window)</h5>
<p class="card-text">I want the modal window to pop up when clickin on the image</p>
</div>
</div>
</div>
<!-- Modal ------------------------------------------------------------------------------------>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Cute Earrings</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>THIS IS THE MODAL!</p>
Buy
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</select>
</section>
<!----- Muuri Filtering ----->
<script>
document.addEventListener('DOMContentLoaded', function () {
var grid = null,
wrapper = document.querySelector('.grid-wrapper'),
searchField = wrapper.querySelector('.search-field'),
filterField = wrapper.querySelector('.filter-field'),
sortField = wrapper.querySelector('.sort-field'),
gridElem = wrapper.querySelector('.grid'),
searchAttr = 'data-title',
filterAttr = 'data-color',
searchFieldValue,
filterFieldValue,
sortFieldValue,
dragOrder = [];
// Init the grid layout
grid = new Muuri(gridElem, {
dragEnabled: false,
layout: {
fillGaps: true
}
});
// Filter field event binding
filterField.addEventListener('change', filter);
// Sort field event binding
sortField.addEventListener('change', sort);
// Filtering
function filter() {
filterFieldValue = filterField.value;
grid.filter(function (item) {
var element = item.getElement(),
isSearchMatch = !searchFieldValue ? true : (element.getAttribute(searchAttr) || '').toLowerCase().indexOf(searchFieldValue) > -1,
isFilterMatch = !filterFieldValue ? true : (element.getAttribute(filterAttr) || '') === filterFieldValue;
return isSearchMatch && isFilterMatch;
});
}
});
</script>
<script src="js/muuri.js"></script>
<script src="https://unpkg.com/web-animations-js#2.3.2/web-animations.min.js"></script>
<!--Modal - Dialog Boxes -->
<script type="text/javascript"> const modals = Array.from(document.querySelectorAll('.modal'));
const triggers = Array.from(document.querySelectorAll('.trigger'));
var closeButton = document.querySelector(".close-button");
//if a trigger is clicked then...
for (const trigger of triggers) {
trigger.addEventListener('click', toggleModal);
}
// .. then toggle it's modal
function toggleModal(event) { event.target.closest('.trigger').querySelector('.modal').classList.toggle("show-modal"); }
// check if the clicked element is a modal, or in a modal
function windowOnClick(event) {
if (modals.some((modal) => modal.contains(event.target))) {
toggleModal();
}
}
</script>
<script>
function closeButton() {
document.getElementByClass('id02').style.display='none'
}
</script>
<!----- JS files ----->
<script type="text/javascript" src="js/scripts.js"></script>
<script type="text/javascript" src="js/singlenav.js"></script>
<script type="text/javascript" src="js/scrollreveal.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload#12.4.0/dist/lazyload.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<i class="icon-chevron-up"></i>
<!----- Lazy Load ----->
<script>
(function() {
function logElementEvent(eventName, element) {
console.log(
Date.now(),
eventName,
element.getAttribute("data-src")
);
}
var callback_enter = function(element) {
logElementEvent("🔑 ENTERED", element);
};
var callback_exit = function(element) {
logElementEvent("🚪 EXITED", element);
};
var callback_reveal = function(element) {
logElementEvent("👁️ REVEALED", element);
};
var callback_loaded = function(element) {
logElementEvent("👍 LOADED", element);
};
var callback_error = function(element) {
logElementEvent("💀 ERROR", element);
element.src =
"https://via.placeholder.com/440x560/?text=Error+Placeholder";
};
var callback_finish = function() {
logElementEvent("✔️ FINISHED", document.documentElement);
};
ll = new LazyLoad({
elements_selector: ".lazy",
load_delay: 300,
threshold: 0,
// Assign the callbacks defined above
callback_enter: callback_enter,
callback_exit: callback_exit,
callback_reveal: callback_reveal,
callback_loaded: callback_loaded,
callback_error: callback_error,
callback_finish: callback_finish
});
})();
</script>
<!----- Scroll To Top ----->
<script>
$(window).scroll(function() {
if ($(this).scrollTop() >= 600) { // If page is scrolled more than 50px
$('#return-to-top').fadeIn(200); // Fade in the arrow
} else {
$('#return-to-top').fadeOut(200); // Else fade out the arrow
}
});
$('#return-to-top').click(function() { // When arrow is clicked
$('body,html').animate({
scrollTop : 0 // Scroll to top of body
}, 500);
});
</script>
</body>
</html>
There are 2 separate issues that are preventing the modal from showing up.
1) The first issue is with your code
The bootstrap library you use returns 404.
How to check if it's happening for you?
Open your browser's inspector, and press CTRL+SHIFT+I
You will see:
Failed to load resource: the server responded with a status of 404 () eylenkim/fullpage/bootstrap-4.3.1-dist/css/bootstrap.css
In fact, this happens for a lot of your relative URLs.
Solution
Replace links to Bootstrap libraries with working ones, eg. from https://getbootstrap.com/
The ones I used in my testing of your code:
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
See gist for minimum code sample for a modal here: https://codepen.io/edwin-chua/pen/rNaLOEg
Once you fix the link problem, you will run into the second issue.
2) The second issue is with your stylesheet
Once you fixed your code as I suggested, you get a dark overlay with no modal.
Removing the reference to https://eylenkim.github.io/ArtByEylen/StyleSheet.css allows the modal to show up, so something in here is interfering with the modal's css.
Here is a working pen: https://codepen.io/edwin-chua/pen/QWwEyyZ
Separate Problem
You seem to have imported some libraries twice, once in the Codepen UI, and once in the HTML file. This will cause you debugging headaches. Make sure you only import them once. Since you are building an entire webpage, I suggest putting all of it in the HTML file.
also see JS tab
And
Further Comments
This section of code seems to be for closing the modal? If so, it probably isn't required, as Bootstrap automatically binds the click events.
<!--Modal - Dialog Boxes -->
<script type="text/javascript"> const modals = Array.from(document.querySelectorAll('.modal'));
const triggers = Array.from(document.querySelectorAll('.trigger'));
var closeButton = document.querySelector(".close-button");
//if a trigger is clicked then...
for (const trigger of triggers) {
trigger.addEventListener('click', toggleModal);
}
// .. then toggle it's modal
function toggleModal(event) { event.target.closest('.trigger').querySelector('.modal').classList.toggle("show-modal"); }
// check if the clicked element is a modal, or in a modal
function windowOnClick(event) {
if (modals.some((modal) => modal.contains(event.target))) {
toggleModal();
}
}
</script>

BootstrapVue collapses with open and close all buttons

This has been troubling me for some time now.
Can someone please help me figure out how to build multiple BootstrapVue collapses that open and close individually. In fact, the opening and closing individually already works, as that comes out of the box. I'd like the Open and Close all buttons to open all or close all collapses when pressed at any point.
https://codepen.io/akolinski/pen/ZNKraN
new Vue({
el: "#app",
data: {
showCollapse: false
}
});
<link href="https://unpkg.com/bootstrap-vue#2.0.0-rc.11/dist/bootstrap-vue.css" rel="stylesheet"/>
<link href="https://unpkg.com/bootstrap#4.1.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue#latest/dist/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<div id='app'>
<div class="row">
<div class="col-12 mt-2">
<h1>Vue with BootstrapVue collapse and open and close all buttons</h1>
<p class="lead">The purpose of this pen is to build multiple BootstrapVue collapses that open and close individually. However we want the Open and Close all buttons to open all or close or collapses when pressed.</p>
<hr>
<div class="row my-3">
<div class="col-12">
<b-button class="mr-2" #click="showCollapse = true">Open all</b-button>
<b-button #click="showCollapse = false">Close all</b-button>
</div>
</div>
<div class="row mb-4">
<div class="col-12">
<b-button v-b-toggle.collapse-1 variant="primary">Toggle Collapse 1</b-button>
<b-collapse id="collapse-1" class="mt-2">
<b-card>
<p class="card-text">Collapse 1 contents Here</p>
</b-card>
</b-collapse>
</div>
</div>
<div class="row mb-4">
<div class="col-12">
<b-button v-b-toggle.collapse-2 variant="primary">Toggle Collapse 2</b-button>
<b-collapse id="collapse-2" class="mt-2">
<b-card>
<p class="card-text">Collapse 2 contents Here</p>
</b-card>
</b-collapse>
</div>
</div>
<div class="row">
<div class="col-12">
<b-button v-b-toggle.collapse-3 variant="primary">Toggle Collapse 3</b-button>
<b-collapse id="collapse-3" class="mt-2">
<b-card>
<p class="card-text">Collapse 3 contents Here</p>
</b-card>
</b-collapse>
</div>
</div>
</div>
</div>
</div>
Thanks to the BootstrapVue community on discord. We came up with this CodePen to show the correct functionality.
Credit: Hiws#0325
https://codepen.io/Hiws/pen/MdvPEX
new Vue({
el: "#app",
data: {
collapses: [
{ show: false },
{ show: false },
{ show: false }
]
},
methods: {
openAll() {
this.collapses.forEach(collapse => {
collapse.show = true
})
},
closeAll() {
this.collapses.forEach(collapse => {
collapse.show = false
})
}
}
});
<link href="https://unpkg.com/bootstrap-vue#2.0.0-rc.11/dist/bootstrap-vue.css" rel="stylesheet"/>
<link href="https://unpkg.com/bootstrap#4.1.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue#latest/dist/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<div id='app'>
<div class="row">
<div class="col-12 mt-2">
<h1>Vue with BootstrapVue collapse and open and close all buttons</h1>
<p class="lead">The purpose of this pen is to build multiple BootstrapVue collapses that open and close individually. However we want the Open and Close all buttons to open all or close or collapses when pressed.</p>
<hr>
<div class="row my-3">
<div class="col-12">
<b-button class="mr-2" #click="openAll">Open all</b-button>
<b-button #click="closeAll">Close all</b-button>
</div>
</div>
<div class="row mb-4" v-for="(collapse, index) in collapses" :key="index">
<div class="col-12">
<b-button #click="collapse.show = !collapse.show" variant="primary">Toggle Collapse {{ index + 1 }}</b-button>
<b-collapse v-model="collapse.show" id="collapse-1" class="mt-2">
<b-card>
<p class="card-text">Collapse {{ index + 1 }} contents Here</p>
</b-card>
</b-collapse>
</div>
</div>
</div>
</div>
</div>

Categories

Resources