Using a function with parameters in a template literal - javascript

I am dynamically inserting html in to the DOM when a form is submitted. When this content is created, I would like to add a delete function when the corresponding button is created. The issue I am facing is that I am unsure how I can use a function in a template literal that has a parameter. My function keeps running when the page loads!
const deletePost = (id) => {
console.log("Delete Button Was clicked ");
}
function renderPost(title, date, body, author, id) {
// renderPost()
postHolder.innerHTML += `<div class="post">
<div class="deleteButton"><button onclick=${deletePost(id)}><i class="fas fa-trash"></i></button></div>
<div class="headerPosted">
<div class="titlePosted">
${title}
</div>
<div class="datePosted">
${date}
</div>
</div>
<div class="bodyPosted">
${body}
</div>
<div class="authorPosted">
-"${author}"
</div>
</div>`;
}
Here is a codepen to test: Codepen

Simply wrap the dynamic variable with ${...}
Try
<button onclick=deletePost(${id})>
Demo:
<script>
const deletePost = (id) => {
console.log("Delete Button Was clicked ");
}
document.addEventListener('DOMContentLoaded', (event) => {
function renderPost(title, date, body, author, id) {
// renderPost()
var postHolder = document.getElementById('postHolder');
postHolder.innerHTML += `<div class="post">
<div class="deleteButton"><button onclick=deletePost(${id})><i class="fas fa-trash"></i></button></div>
<div class="headerPosted">
<div class="titlePosted">
${title}
</div>
<div class="datePosted">
${date}
</div>
</div>
<div class="bodyPosted">
${body}
</div>
<div class="authorPosted">
-"${author}"
</div>
</div>`;
}
renderPost('test',new Date(),'some body','test author',123);
});
</script>
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<div id="postHolder"></div>

Related

Why when I create several html tags with javascript then I can not delete it with the same javascript?

When I create a form with the write () command, then I want to delete it, but I can't. What is the cause of this problem?
In order to do this correctly, what command should I use or what should I change in my code?
var btn = document.querySelector('#btn');
var btn_alert = document.querySelector('#btn-alert');
var content = document.querySelector('.popup-container');
var div1 = document.getElementById('div1');
function message(message, btn) {
document.write('<div id="div1"><div id="content" class="popup-container"><div class="box-item"><div class="icon-success"><span class="span1"></span> <span class="span2"></span><div class="ring"></div></div><h2 class="alert-title">Good job!</h2><div class="alert-content">' + message + '</div><div class="actions-btn"><button onclick="ok()" class="btn-alert" id="btn-alert">' + btn + '</button></div></div></div></div>')
}
function ok() {
div1.removeChild(content);
}
<button class="btn-alert" id="btn">OK</button>
<!-- <div id="content" class="popup-container dis-active">
<div class="box-item">
<div class="icon-success">
<span class="span1"></span>
<span class="span2"></span>
<div class="ring"></div>
</div>
<h2 class="alert-title">Good job!</h2>
<div class="alert-content">is ok.</div>
<div class="actions-btn">
<button class="btn-alert" id="btn-alert">OK</button>
</div>
</div>
</div> -->
<script src="script.js"></script>
<script>
message("خوش اومدی!", "کلیک کن");
</script>
document.write is really outdated. In your script you write the elements to the document after you're trying to retrieve them. That won't work.
Here is an example snippet using insertAdjacentHTML to create a message element with a button to remove it.
It is generally not a good idea to use inline event handlers. The snippet uses event delegation to handle button clicks.
It may be wise to first learn more about html document manipulation or javascript.
document.addEventListener(`click`, handle);
const create = () => message(`خوش اومدی!`,`کلیک کن`);
create();
function handle(evt) {
if (evt.target.id === `btn-alert`) {
document.getElementById('div1').remove();
}
if (evt.target.id === `recreate`) {
create();
}
}
function message(message, btnTxt) {
document.body.insertAdjacentHTML(`beforeEnd`, `
<div id="div1">
<div id="content" class="popup-container">
<div class="box-item">
<div class="icon-success">
<span class="span1"></span>
<span class="span2"></span>
<div class="ring"></div>
</div>
<h2 class="alert-title">Good job!</h2>
<div class="alert-content">${message}</div>
<div class="actions-btn">
<button class="btn-alert" id="btn-alert">${btnTxt}</button>
</div>
</div>
</div>
</div>`);
}
<button id="recreate">(re)create message</button>

Loop over API data and display multiple search items in the DOM with JavaScript

I'm trying to set up a search API app, using the https://restcountries.eu/ API and axios.
I've managed to display everything in the DOM, as I want. However, if I search for "United", or something with only part of the name. It either displays undefined or if I loop though it'll only display the last search item. I'd like to bring all the search items into the DOM, under any search criteria I input.
Below is the HTML:
<body>
<div class="search-container">
<form id="form" class="form">
<input type="text" id="search" placeholder="Search for country..." />
</form>
</div>
<main id="main">
<div id="map" class="google-map"></div>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script src="script.js"></script>
</body>
</html>
And here's the JS:
const APIURL = 'https://restcountries.eu/rest/v2/name/'
// const GOOGLE_MAPS_API = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyDhlU1KMTlTh4C__bTJBxbVA-s7wvQbO9E&callback=initMap'
const main = document.getElementById('main')
const form = document.getElementById('form')
const search = document.getElementById('search')
async function getCountryData(name) {
try {
const { data } = await axios.get(APIURL + name)
data.forEach(res => {
let countryArr = res
createCountryCard(countryArr)
} )
} catch (err) {
if(err.response.status == 404) {
createErrorCard('No countries found')
setTimeout(() => {
main.innerHTML = ''}
, 1500);
}
}
}
function createCountryCard(country) {
const cardHTML = `
<div class="content-container">
<div class="card">
<div class="wrapper">
<div class="card-title">
<h2>${country.name}</h2>
<h4>Capital: ${country.capital}</h4>
<h5>Population: ${country.population.toLocaleString('en')}</h5>
</div>
<div class="card-image">
<img
src="${country.flag}"
alt="${country.name +'-flag'}"
/>
</div>
</div>
<div class="wrapper">
<div class="map-content">
<div id="map" class="google-map"></div>
</div>
<div class="card-content">
<ul class="card-list">
<li><strong>Region:</strong> ${country.region}</li>
<li><strong>Subregion:</strong> ${country.subregion}</li>
<li><strong>Currency:</strong> ${country.currencies[0].name}<span> ${country.currencies[0].symbol}</span></li>
<li><strong>Spoken Language:</strong> ${country.languages[0].name}</li>
<li><strong>Timezone:</strong> ${country.timezones}</li>
</ul>
</div>
</div>
</div>
</div>
`
main.innerHTML = cardHTML
console.log(country)
}
function createErrorCard(msg) {
const cardHTML = `
<div class="card">
<h1>${msg}</h1>
</div>
`
main.innerHTML = cardHTML
}
// Search Input
form.addEventListener('submit', (e) => {
e.preventDefault()
const countryName = search.value
if(countryName) {
getCountryData(countryName)
search.value = ''
}
})
Any help would be much appreciated.
Thanks
main.innerHTML = cardHTML line in createCountryCard() function overwrites the content of the #main element with each loop iteration. That's why you are only getting the last item from your search results. Try changing it to main.innerHTML += cardHTML.

Can i querySelectorAll buttons that previously added with (element.innerHTML)?

I want to make array of all the buttons that inside the article tags.
When i select all buttons -i mentioned- that i added with (element.innerHTML) to use it in my JavaScript code,it doesn't work.
I tried to console.log the selected buttons but console gives me an empty array?
is there a wrong in my way of selection or there's another way to reuse that buttons in my JavaScript code?
const productsCenter = document.querySelector(".products-center");
class Displayproducts {
async getData() {
try {
let response = await fetch("products.json");
let data = await response.json();
let products = data.items;
let mapped = products.map((el) => {
const { title, price } = el.fields;
const image = el.fields.image.fields.file.url;
const id = el.sys.id;
return { title, price, image, id };
});
return mapped;
} catch (err) {
console.log(err);
}
}
}
class UI {
displayProducts(products) {
products.forEach((product) => {
let result = `<article class="product">
<div class="img-container">
<img
src="${product.image}"
alt="product"
class="product-img"
/>
<button class="bag-btn" data-id="${product.id}">
<i class="fas fa-shopping-cart"></i>
add to bag
</button>
</div>
<h3>${product.title}</h3>
<h4>${product.price}</h4>
</article>`;
productsCenter.innerHTML += result;
});
}
}
window.onload = () => {
const product = new Displayproducts();
const ui = new UI();
product.getData().then((products) => {
ui.displayProducts(products);
});
const bagBtns = [...document.querySelectorAll(".bag-btn")];
console.log(bagBtns);
};
<body>
<!-- start of nav bar -->
<nav class="navbar">
<div class="navbar-center">
<span class="nav-icon">
<i class="fas fa-bars"></i>
</span>
<img
src="C:\Users\iman\Desktop\comfy-house\images\logo.svg"
alt="logo"
/>
<div class="cart-btn"></div>
<span class="nav-icon">
<i class="fas fa-cart-plus"></i>
</span>
<div class="cart-items">0</div>
</div>
</nav>
<!-- end of nav bar -->
<!-- start of header -->
<header class="hero">
<div class="banner">
<h1 class="banner-title">furniture collection</h1>
<button class="banner-btn">shop now</button>
</div>
</header>
<!-- end of header -->
<!-- start of cart -->
<div class="cart-overlay">
<div class="cart">
<span class="close-cart">
<i class="fas fa-window-close"></i>
</span>
<h2>your cart</h2>
<div class="content"></div>
<!-- start of cart item -->
<!-- end of cart item -->
</div>
</div>
<!-- end of cart -->
<!-- start of products-->
<section class="products">
<div class="section-title">
<h2>our products</h2>
</div>
<div class="products-center">
</div>
</section>
<!-- end of products -->
<script src="app.js"></script>
</body>
In the window.onload function the const bagBtns = [...document.querySelectorAll(".bag-btn")]; line happened before the ui.displayProducts(products); line - you can see, add console.log('after') inside the callback function and see what happen.
This happen because - read this article
sulotions:
use async await
move the next lines:
const bagBtns = [...document.querySelectorAll(".bag-btn")];
console.log(bagBtns);
after:
ui.displayProducts(products);

why the value of productsCenter variable is null?

i want to know wher the error came from, i'm trying to make an ecommerce project with vanilla javaScript, when i start display the products, json data is fetched correctly as a first step, but when i excecuted displayProducts() function it didn't work!
the error message i got:
Uncaught (in promise) TypeError: Cannot set property 'innerHTML' of null.
i tried console.log(document.querySelector("products-center")) but the result was null, i also made sure that the js script tag is after html tags.
const productsCenter = document.querySelector("products-center");
class Displayproducts {
async getData() {
try {
let response = await fetch("products.json");
let data = await response.json();
let products = data.items;
let mapped = products.map((el) => {
const { title, price } = el.fields;
const image = el.fields.image.fields.file.url;
const id = el.sys.id;
return { title, price, image, id };
});
return mapped;
} catch (err) {
console.log(err);
}
}
}
class UI {
displayProducts(products) {
products.forEach((product) => {
productsCenter.innerHTML = `<article class="product">
<div class="img-container">
<img
src="${product.image}"
alt="product"
class="product-img"
/>
<button class="bag-btn">
<i class="fas fa-shopping-cart"></i>
add to bag
</button>
</div>
<h3>${product.title}</h3>
<h4>${product.price}</h4>
</article>`;
});
}
}
window.onload = () => {
const product = new Displayproducts();
const ui = new UI();
product.getData().then((products) => {
ui.displayProducts(products);
});
};
<body>
<!-- start of nav bar -->
<nav class="navbar">
<div class="navbar-center">
<span class="nav-icon">
<i class="fas fa-bars"></i>
</span>
<!-- <img
src="https://i.pinimg.com/originals/dd/79/2d/dd792d5596291f410cb8e7ce10a7e91a.png"
alt="logo"
/> -->
<div class="cart-btn"></div>
<span class="nav-icon">
<i class="fas fa-cart-plus"></i>
</span>
<div class="cart-items">0</div>
</div>
</nav>
<!-- end of nav bar -->
<!-- start of header -->
<header class="hero">
<div class="banner">
<h1 class="banner-title">furniture collection</h1>
<button class="banner-btn">shop now</button>
</div>
</header>
<!-- end of header -->
<!-- start of cart -->
<div class="cart-overlay">
<div class="cart">
<span class="close-cart">
<i class="fas fa-window-close"></i>
</span>
<h2>your cart</h2>
<div class="content"></div>
<!-- start of cart item -->
<!-- end of cart item -->
</div>
</div>
<!-- end of cart -->
<!-- start of products-->
<section class="products">
<div class="section-title">
<h2>our products</h2>
</div>
<div class="products-center">
</div>
</section>
<!-- end of products -->
<script src="app.js"></script>
</body>
document.querySelector("products-center"); searches for a DOM element which tag is named "products-center" (something like: <products-center></products-center>). And since this doesn't exist, productsCenter doesn't contain any valid DOM, and so you cannot set its innerHTML.
I can see <div class="products-center"> in your HTML, so I guess you meant to use const productsCenter = document.querySelector(".products-center"); (note the .).

How to load XML data on button click?

I created a sample code to view xml data. When the page is loading, my current code load full xml file. But I need to load XML file after the button click. How can I fix the issue?
here is the code
$(document).ready(function(){
$.ajax({
type:"GET",
url:"contact.xml",
dataType:"xml",
success:showCD
});
});
function showCD(xml){
xml = $(xml).children();
$(xml).children().each(function () {
let TITLE = $(this).find("TITLE").text();
let ARTIST =$(this).find("ARTIST").text();
let COUNTRY = $(this).find("COUNTRY").text();
let COMPANY =$(this).find("COMPANY").text();
let html = `<div class="col-md-4">
<div class="thumbnail">
<p>${TITLE}</p>
<p>${ARTIST}</p>
<p>${COUNTRY}</p>
<p>${COMPANY}</p>
</div> </div>`;
$("#xmldata").append(html);
});
}
<section>
<div class="container">
<input type="button" value="View All" id="myButton1" class="reveal" style="float: right;" onclick="toggler('toggle_container');">
<div id="toggle_container" class='hide'>
<div class="block">
<div class="row" id="xmldata"></div>
</div>
</div>
</div>
</section>
Plunker
Just add a click event listener to the button and put the AJAX request inside the handler.
$(document).ready(function(){
// adding click event listener to the button
$('#myButton1').on('click', function() {
// make the AJAX request
$.ajax({
type:"GET",
url:"contact.xml",
dataType:"xml",
success:showCD
});
});
});
function showCD(xml){
xml = $(xml).children();
$("#xmldata").empty();
xml.each(function () {
let TITLE = $(this).find("TITLE").text();
let ARTIST =$(this).find("ARTIST").text();
let COUNTRY = $(this).find("COUNTRY").text();
let COMPANY =$(this).find("COMPANY").text();
let html = `<div class="col-md-4">
<div class="thumbnail">
<p>${TITLE}</p>
<p>${ARTIST}</p>
<p>${COUNTRY}</p>
<p>${COMPANY}</p>
</div> </div>`;
$("#xmldata").append(html);
});
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<section>
<div class="container">
<input type="button" value="View All" id="myButton1" class="reveal" style="float: right;" onclick="toggler('toggle_container');">
<div id="toggle_container" class='hide'>
<div class="block">
<div class="row" id="xmldata"></div>
</div>
</div>
</div>
</section>

Categories

Resources