How to create a onclick event for each search results items so that it render a product page with meta data of that item. I have successfully able to filter items as per keypress. Now I want to give a click event for filtered item to open a product page. How would I do that in Javascript? Please help me figure out this.
**My HTML code**
<!-- Search form -->
<div class="container">
<div class="active-pink-4 mb-4 mt-4">
<input class="form-control form_search" type="text" placeholder="Search" aria-label="Search" id="search">
</div>
<div id="match-list" name="matchid"></div>
</div><!-- End of Search form -->
<div class="container"><!-- Strat of login container-->
<div class="row" id="viewhide"><!-- Strat of login row-->
<div class="col-md-6 d-none d-sm-block"><!--start of col login img-->
<img src="https://img.etimg.com/thumb/width-1200,height-900,imgsize-27424,resizemode-1,msid-14351710/industry/healthcare/biotech/pharmaceuticals/free-medicines-to-all-patients-in-government-hospitals-from-november.jpg">
</div><!--End of col login img-->
<div class="col-md-6 text-center fadeIn first"><!--Start col login-->
<h2>Sign In</h2>
<!-- Login Form -->
<form>
<input type="text" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Username">
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
<div id="formFooter">
<a class="underlineHover mb-2" href="#">Forgot Password?</a>
</div>
<input type="submit" class="btn btn-primary d-flex justify-content-center d-md-table mx-auto mb-2 btn-round" value="Login">
<h5>You don't have an account ?</h5>
<input type="button" class="btn btn-primary d-flex justify-content-center d-md-table mx-auto mb-5 btn-round" value="Register">
</form>
</div><!-- End of col login-->
</div><!-- End of login row-->
</div><!-- End of login container-->
**My Js code:**
const search = document.getElementById('search');
const matchList = document.getElementById('match-list');
// Search states.json and filter it
const searchStates = async searchText =>{
const res = await fetch('lib/json/data.json').then(response =>{
//console.log(response);
if (!response.ok) {
throw Error("Error");
}
return response.json();
}).then(data =>{
//console.log(data.item);
let states = data.item;
//console.log(states, "states");
// Get matches to current text input
let matches = states.filter(state =>{
const regex = new RegExp(`^${searchText}`, `gi`);
return state.itemName.match(regex) || state.itemMfrCode.match(regex);
});
let divhide = document.getElementById('viewhide');
if(searchText.length !== 0){
divhide.style.display = "none";
}else{
divhide.style.display = "flex";
}
//Hide all results when input is empty
if (searchText.length === 0) {
matches = [];
matchList.innerHTML = '';
}
//Hide if no results are found
if (searchText !== states) {
match = [];
matchList.innerHTML = '';
}
outputHtml(matches);
}).catch(error =>{
console.log(error);
});
};
//Show results in HTML
const outputHtml = matches => {
if (matches.length > 0) {
const html = matches.map(match => `
<div class="card card-body mb-1" id="medprod" name="selectid"
onclick="getproduct()">
<h4 style="cursor: pointer;">${match.itemName}</h4>
</div>
`).join('');
matchList.innerHTML = html;
}
}
search.addEventListener('input', () => searchStates(search.value));
//On clcik search result items function
function getproduct(){
}
**My Json structure**
{
"clientId": "1234",
"systemId": "2010",
"orderReferenceNo": "43442",
"responseCode": "0000",
"responseDescription": "Items successfully retrieved!",
"item": [
{
"itemMfrCode": "0001001",
"qnty": "00000000",
"itemName": "clinic shampoo",
"unitPk": "30ml",
"itemCategory": " ",
"itemType": "NT",
"schemeRange": "000",
"schemeOffeQty": "000",
"rateDiffFlag": "N",
"schemeHalfValueFlag": " ",
"schemeHalfValuePerc": null,
"ratePerUnit": 20.00
},
{},
}
I should have posted the answer long before. No problem, hope it helps someone in future.
const search = document.getElementById('search');
const matchList = document.getElementById('match-list');
const productLayout = document.getElementById('product_layout');
//Search filter
const searchStates = async searchText => {
const res = await
fetch('https://data.json').then(response => {
if (!response.ok) {
throw Error("Error");
}
return response.json();
}).then(data => {
console.log(data.item);
let states = data.item;
console.log(states, "states");
matchList.style.display = 'block';
// Get matches to current text input
let matches = states.filter(state => {
const regex = new RegExp(`^${searchText}`, `gi`);
return state.itemName.match(regex) ||
state.itemMfrCode.match(regex);
});
if (searchText.length !== 0) {
productLayout.style.display = 'none';
} else {
productLayout.style.display = 'block';
}
outputHtml(matches);
}).catch(error => {
console.log(error);
});
};
//Show results in HTML
const outputHtml = matches => {
if (matches.length > 0) {
//Meta data of clicked item
//Keep adding
//${match.itemId},${match.itemRate},${match.itemColor} to the list.
const html = matches.map(match => `
<li id="${match.itemMfrCode}">${match.itemName}</li>
`).join('');
matchList.innerHTML = html;
}
}
search.addEventListener('input', () => searchStates(search.value));
/*OnClick filtered items*/
matchList.addEventListener('click', function(e) {
var target = e.target;
while (target && target.parentNode !== matchList) {
target = target.parentNode;
if (!target) {
return;
}
}
if (e.target.tagName === 'LI') {
//Get selected product name
let liInnerText = e.target.innerText;
//Store prod name in localStorage
localStorage.setItem('liText', liInnerText);
//Insert selected item in input text field
search.value = liInnerText;
//Hide search dropdown after click event
matchList.style.display = 'none';
/*View product layout*/
productLayout.style.display = 'block';
//Get product name from localStorage
var selectedName = localStorage.getItem('liText');
//Dispaly product name in HTML page
document.getElementById('prod_name').innerHTML =
selectedName;
}
});
#match-list {
display: none;
}
#product_layout {
display: none;
}
<!-- Search form -->
<div class="container" id="search_layout">
<div class="active-pink-4 mb-2 mt-4">
<input class="form-control form_search" type="text" placeholder="Search" aria-label="Search" id="search" value="" autocomplete="off" onfocus="this.value=''">
</div>
<ul id="match-list" name="matchid"></ul>
</div>
<!-- End of Search form -->
<!--Product details-->
<div class="container-fluid" id="product_layout">
<div>
<p id="prod_name"></p>
</div>
Related
I have an input type file and when I click, it will select a particular image, likewise some other input type text which i have to use to collect data from the user and I am as well having a button to set the data into the localStorage once the button is clicked.
Onload of the page, I want the information on the localStorage (productImg, productName, productOldPrice, productCategory, productNewPrice, productSavePrice) to display on the browser.
Note: Every other information are displaying except the productImg which is why am asking this question.
What I wanted to archive is a way of setting each product image into the localStorage and when displaying it on the browser, each product image should be display on the designated place.
<button id="adminSponsorPush" class="btn btn-lg btn-success " style="width: 30%;" onclick="text()">Sponsored Products</button>
<input type="file" id="adminDealImg">
<input type="text" name="" id="adminDealName" placeholder="Product Name">
<input type="text" name="" id="adminOldPrice" placeholder="deals Old Price">
<input type="text" name="" id="adminNewPrice" placeholder="deals new Price">
<button type="button" onclick="setIt()" class="btn btn-primary">Understood</button>
<div id="todaysDeal" class="d-flex flex-wrap w-100 gap-3 p-2 border border-danger border-2"></div>
This is the JavaScript code that set the data into the localStorage
let allProducts = [];
if (localStorage.companyProduct) {
allProducts = JSON.parse(localStorage.getItem("companyProduct"));
}
text = () => {
let products = {
firstName: "",
lastName: "",
email: "",
phoneNumber: "",
password: "",
topDeal: [],
sponsorProduct: [],
recommendedProduct: [],
inspiredProduct: [],
laptops: [],
smartPhone: [],
healthBeauty: [],
groceries: [],
videoGames: [],
mobileAccessories: [],
homeFurnishings: [],
fitnessToolsEquipment: [],
kidsWearAccessories: [],
topDealOnTelevision: [],
};
allProducts.push(products);
localStorage.setItem("companyProduct", JSON.stringify(allProducts));
};
setIt = () => {
for (let index = 0; index < allProducts.length; index++) {
let topDealProduct = {
productImg: adminDealImg.value,
productName: adminDealName.value,
productOldPrice: adminOldPrice.value,
productCategory: `product`,
productNewPrice: adminNewPrice.value,
productSavePrice: `You save ₦${adminOldPrice.value - adminNewPrice.value}`,
};
allProducts[index].topDeal.push(topDealProduct);
localStorage.setItem("companyProduct", JSON.stringify(allProducts));
localStorage.setItem("currentUserIndex", index);
}
};
This is the javaScript code that will display the information into the browser when the page is load
currentProductIndex = localStorage.getItem("currentUserIndex");
displayProducts = () => {
todaysDeal.innerHTML = "";
eachTopDealProduct = allProducts[currentProductIndex].topDeal;
for (let index = 0; index < eachTopDealProduct.length; index++) {
todaysDeal.innerHTML += `
<div onclick="topDealProductPage(${index})" class="d-flex p-3 shadow each-todays-deal gap-3"
style="width: 32.5%; height: 120px; cursor: pointer;"
>
<img src="${eachTopDealProduct[index].productImg}" alt="" id="dealsImg"/>
<div class="d-flex flex-column gap-3">
<div class="text-capitalize" id="dealsProductName">${eachTopDealProduct[index].productName}</div>
<div class="">
<div class="d-flex gap-2">
<div class="fw-bold fs-4" id="dealsPrice">₦${eachTopDealProduct[index].productNewPrice}</div>
<div class="fw-bold fs-6 my-auto text-decoration-line-through text-secondary" id="dealsPrice">₦${eachTopDealProduct[index].productOldPrice}</div>
</div>
<div class="fw-bold" style="font-size: 12px; color: #33B27B;" id="dealsSave">${eachTopDealProduct[index].productSavePrice}</div>
</div>
</div>
</div>
`;
}
};
Get file data from onChange callback and transfer it to base64, then set base64 to LocalStorage.
<input type="file" id="adminDealImg">
<img src="" id="img" alt="">
<script>
if(localStorage.getItem('img-BASE64')){
document.querySelector('#img').src=localStorage.getItem('img-BASE64')
}
function getBase64(file) {
return new Promise((resolve,reject)=>{
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
resolve(reader.result)
};
reader.onerror = reject
})
}
document.querySelector('#adminDealImg').addEventListener('change', async(e)=>{
const data = await getBase64(e.target.files[0])
localStorage.setItem('img-BASE64', data)
})
</script>
After you have changed the question.
Set img data to localStorage is different from normal data.
// error here
productImg: adminDealImg.value,
you can set image base64 data as a unique key and get it by this key as identity, maybe email ?
LocalStorage.setItem(img-Base64-${email}, 'sth base64')
Please click LIKE button. Orz....
I managed to upload an image in form, but i want to save it to backend and then when i call it again using frontend i will b able to save a picture
function code :
addFilm: (title, description, release_year, language_id, rental_duration, rental_rate, length, replacement_cost, rating, special_features, category_id, actors, store_id, callback) => { //1.(1 ~ 3 are places to change code )
var conn = db.getConnection(); // GET CONNECTION TO DB
conn.connect((err) => {
if (err) {
console.log(err);
return callback(err, null);
} else {
console.log('Connected Successfully!');
var SQLstatement = //use backtick to go onto next line
// first insert into film table
`insert into film (title,description,release_year,language_id,rental_duration,rental_rate,length,replacement_cost,rating,special_features)
Values(?,?,?,?,?,?,?,?,?,?)`; // 2.
conn.query(SQLstatement, [title, description, release_year, language_id, rental_duration, rental_rate, length, replacement_cost, rating, special_features], (error, result_id) => { //3.
if (error) {
console.log(error);
return callback(error, null);
}
else {
// second insert into film_category table
var SQLstatement = `insert into film_category (film_id,category_id) Values (?,?)`
conn.query(SQLstatement, [result_id.insertId, category_id], (error, result) => {
if (error) {
console.log(error);
return callback(error, null);
}
else {
console.log(result);
// neeed check actor
console.log(actors);
var SQLstatement = ''
values = []
// add a new actor id with the same film id to the film_actor table
for (var k = 0; k < actors.length; k++) {
if (k == actors.length - 1) {
SQLstatement += `(?,?)`
}
else {
SQLstatement += `(?,?),`
}
// console.log(actors[k])
values.push(actors[k])
values.push(result_id.insertId)
}
var finalSQLstatement = `insert into film_actor (actor_id,film_id) Values ` + SQLstatement
conn.query(finalSQLstatement, values, (error, result) => {
if (error) {
console.log(error);
return callback(error, null);
}
})
console.log(result_id.insertId);
var SQLstatement = //use backtick to go onto next line
// last insert into inventory with same film_id and store_id
`insert into inventory(film_id,store_id) Values(?,?)`; // 2.
conn.query(SQLstatement, [result_id.insertId, store_id], (error, result) => { //3.
conn.end();
if (error) {
console.log(error);
return callback(error, null);
}
else {
console.log(result);
return callback(null, result.insertId);
}
});
}
})
// });
}
});
}
});
},
app.get():
app.get('/view/:filmid',function(req, res){
var filmid = req.params.filmid;
actorDB.getDetails(filmid, function(err, result){
if(!err){
console.log(result);
res.send(result);
}else{
res.status(500).send("Some error");
}
});
});
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Customer</title>
<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">
</head>
<body>
<div class="container">
<nav class="nav">
<a class="nav-link" href="/">Home</a>
<a class="nav-link" href="/users/">All Users</a>
</nav>
<h1>Register a new DVD</h1>
<form id="register-form">
<div class="form-group">
<div class="file-upload w-100">
<form class="image-upload-wrap d-flex justify-content-center align-items-center"
style="height: 240px">
<input class="file-upload-input" type="file" onchange="readImage(this);" accept="image/*"
id="imageFile" />
<div class="drag-text w-100 d-flex flex-column justify-content-center align-items-center">
<div id="imageErr" class="text-danger d-none">
Invalid Image
</div>
<h3>Drag photo here</h3>
<p>— or —</p>
<button class="btn bg-secondary text-white font-weight-bold text-center" type="button"
style="white-space: nowrap; z-index: 1055" id="addImage"
onclick="$('.file-upload-input').trigger( 'click' )">
Choose photo to upload
</button>
</div>
</form>
<div class="file-upload-content">
<img class="file-upload-image" style="border: 1px black solid" src="#" alt="your image"
id="imgPreview" />
</div>
</div>
</div>
<div class="form-group">
<label for="title">title:</label>
<input type="text" class="form-control" id="title" required>
</div>
<div class="form-group">
<label for="description">Description:</label>
<input type="text" class="form-control" id="description" required>
</div>
<div class="form-group">
<label for="release">Release:</label>
<input type="text" class="form-control" id="release" required>
</div>
<div class="form-group">
<label for="lang">Language_id:</label>
<input type="text" class="form-control" id="lang" required>
</div>
<div class="form-group">
<label for="rental_duration">Rental Duration:</label>
<input type="text" class="form-control" id="rental_duration" required>
</div>
<div class="form-group">
<label for="rental_rate">Rental rate:</label>
<input type="text" class="form-control" id="rental_rate" required>
</div>
<div class="form-group">
<label for="length">Length:</label>
<input type="text" class="form-control" id="length" required>
</div>
<div class="form-group">
<label for="replacement_cost">Replacement Cost:</label>
<input type="text" class="form-control" id="replacement_cost" required>
</div>
<div class="form-group">
<label for="rating">Rating:</label>
<input type="text" class="form-control" id="rating" required>
</div>
<div class="form-group">
<label for="special_features">Special Features:</label>
<input type="text" class="form-control" id="special_features" required>
</div>
<div class="form-group">
<label for="category_id">Category ID:</label>
<input type="text" class="form-control" id="category_id" required>
</div>
<div class="form-group">
<label for="actors">Actors:</label>
<input type="text" class="form-control" id="actors" required>
</div>
<div class="form-group">
<label for="store_id">Store_id:</label>
<input type="text" class="form-control" id="store_id" required>
</div>
<button type="submit" class="btn btn-primary">Register</button>
<button type="reset" class="btn btn-primary ml-5">Reset</button>
<button type="button" class="btn btn-primary ml-5" id="Logout">Log Out</button>
<!-- <input type="reset" value="Reset"> -->
</form>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" 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://unpkg.com/axios/dist/axios.min.js"></script>
<script>
const baseUrl = "http://localhost:8081";
const token = localStorage.getItem("token");
const loggedInUserID = parseInt(localStorage.getItem("loggedInUserID"));
console.log(token, loggedInUserID)
function readImage(fileInput) {
if (fileInput.files && fileInput.files[0]) {
var imgReader = new FileReader();
imgReader.onload = function (event) {
var wrap = document.querySelector(".image-upload-wrap");
if (wrap) {
wrap.classList.add("d-none");
wrap.classList.remove("d-flex");
}
var imgData = event.target.result.split(',')[1];
var postData = { image: imgData };
fetch('/upload-image.php', {
method: 'POST',
body: JSON.stringify(postData),
headers: { 'Content-Type': 'application/json' }
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch(error => {
console.error('Error:', error);
});
document.getElementById("addImage").style.display = "none";
var imgPreview = document.getElementById("imgPreview");
imgPreview.src = event.target.result;
var content = document.querySelector(".file-upload-content");
content.classList.add("d-flex", "justify-content-center", "align-items-center");
content.classList.remove("d-none");
var btnSave = document.getElementById("save");
if (btnSave.classList.contains("btn-danger")) {
btnSave.classList.toggle("btn-danger");
btnSave.classList.add("btn-primary");
btnSave.innerHTML = "Save as promo picture";
}
};
imgReader.readAsDataURL(fileInput.files[0]);
} else {
removeUpload();
}
}
if (token === null || isNaN(loggedInUserID)) {
window.location.href = "http://localhost:3001/home";
} else {
$("#register-form").submit((event) => {
// prevent page reload
event.preventDefault();
const title = $("#title").val();
const description = $("#description").val();
const release = $("#release").val();
const lang = $("#lang").val();
const rental_duration = $("#rental_duration").val();
const rental_rate = $("#rental_rate").val();
const length = $("#length").val();
const replacement_cost = $("#replacement_cost").val();
const rating = $("#rating").val();
const feature = $("#special_features").val();
const category_id = $("#category_id").val();
const actors = $("#actors").val();
const store_id = $("#store_id").val();
const requestBody = {
title: title,
description: description,
release_year: release,
language_id: lang,
rental_duration: rental_duration,
rental_rate: rental_rate,
length: length,
replacement_cost: replacement_cost,
rating: rating,
special_features: feature,
category_id: category_id,
actors: actors,
store_id: store_id
};
let token = localStorage.getItem("token");
console.log(requestBody);
axios.post(`${baseUrl}/film`, requestBody, { headers: { "Authorization": "Bearer " + token } })
.then((response) => {
console.log(requestBody)
window.location.href = "http://localhost:3001/home";
})
.catch((error) => {
console.log(error);
if (error.response.status === 400) {
alert("Validation failed");
} else {
alert("Something unexpected went wrong.");
}
});
});
$("#Logout").click(function () {
window.localStorage.clear();
localStorage.removeItem("token");
localStorage.removeItem("loggedInUserID");
window.location.assign("http://localhost:3001/login");
});
}
</script>
</body>
</html>
I need help in parsing the data, even now as i try to submit the form it says Cannot read properties of null (reading 'classList')
at imgReader.onload.
how can I pass value from form into store and then display dynamically a list of those input items? I am trying to make a shopping list which would be passed via form and then displayed below in ul list below.
collectRefs() {
this.form = this.rootElement.querySelector("form");
this.shopList = this.rootElement.querySelector("#shop-list"); }
applyHandlers() {
const store = createStore(rootReducers);
store.subscribe(() => {
this.shopList.innerText = `${store.getState().addProduct}`
// {.map((value, index) => <li key={index}>{value}</li>)}
console.log("stan przy subscribe " +store.getState().addProduct)
});
this.form.addEventListener('click', () => {
store.dispatch(addProduct(this.form.value))
console.log("to jest wynik " + `${store.getState().addProduct}`)
});
}
createUI(rootElement) {
this.rootElement = rootElement;
this.rootElement.innerHTML = `
<div class="card-header">Lista zakupów</div>
<div class="card-body">
<form>
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Produkt..." />
<div class="input-group-append">
<button class="btn btn-outline-primary" type="button" id="shop-add">Dodaj</button>
</div>
</div>
</form>
<ul class="list-group mt-3" id="shop-list">
</ul>
</div>
`;
}
REDUCER:
const initState = [];
function addProduct(state = initState, action) {
switch (action.type) {
case ADD_PRODUCT:
return [...state, action.payload]
default:
return state;
}
}
I have a simple for with 3 fields using vue.js, I am setting up "floating labels" on focus, as of now I have the inputs working nicely adding and removing class "active" as expected. When I try to add "textarea" my app is breaking and returning "cannot read value of null", is there a way to add the textarea as the inputs are setup?
html:
<form #submit.prevent="submitForm()">
<div class="form-group">
<div id="floatWrapper" class="float-wrapper">
<label for="floatField">Enter Your Name</label>
<input
id="floatField"
v-model="contact_name"
type="text"
class="form-control form-control--email"
#input="$v.contact_name.$touch"
/>
</div>
<p v-if="$v.contact_name.$dirty">
<span v-if="!$v.contact_name.required" class="form__alert">
Please enter your name.
</span>
</p>
<div id="floatWrapper" class="float-wrapper">
<label for="floatField">Enter Your Email</label>
<input
v-model="contact_email"
type="email"
class="form-control form-control--email"
/>
</div>
<p v-if="$v.contact_email.$dirty">
<span v-if="!$v.contact_email.required" class="form__alert">
Email is required.
</span>
<span v-if="!$v.contact_email.email" class="form__alert">
Please enter a valid email
</span>
</p>
<div id="floatWrapper" class="float-wrapper">
<label for="floatField">Enter Your Message</label>
<textarea
v-model="contact_message"
class="form-control form-control--textarea"
rows="5"
/>
</div>
<p v-if="$v.contact_message.$dirty">
<span
v-if="!$v.contact_message.required"
class="form__alert"
>
Message must be over 10 characters
</span>
</p>
</div>
<button
type="submit"
data-cursor="hover"
class="btn btn-primary"
>
Send Message
<font-awesome-icon far icon="arrow-right" />
</button>
</form>
js:
mounted() {
const labelFloating = (() => {
const isFocus = (e) => {
const target = e.target
target.parentNode.classList.add('active')
}
const isBlur = (e) => {
const target = e.target
if (!target.value) {
target.parentNode.classList.remove('active')
}
}
const bindEvents = (element) => {
const field = element.querySelector('input')
field.addEventListener('focus', isFocus)
field.addEventListener('blur', isBlur)
const text = element.querySelector('textarea')
text.addEventListener('focus', isFocus)
text.addEventListener('blur', isBlur)
}
const initialize = () => {
const floatWraps = document.querySelectorAll('.float-wrapper')
floatWraps.forEach((element) => {
if (element.querySelector('input').value) {
element.classList.add('active')
} if (element.querySelector('textarea').value) {
element.classList.add('active')
}
bindEvents(element)
})
}
return {
init,
}
})()
labelFloating.init()
},
The if (element.querySelector('input').value) { will throw that error because you're chaining .value off the selector, but it doesn't exist and returns null. try this instead:
const selector = element.querySelector('input') || element.querySelector('textarea')
if (selector && selector.value) {
element.classList.add('active')
bindEvents(element)
}
And use the same refactor for the bindEvents method:
const bindEvents = (element) => {
const field = element.querySelector('input') || element.querySelector('textrea')
field.addEventListener('focus', isFocus)
field.addEventListener('blur', isBlur)
}
Good Day!
I'm working on my project right now and I need to dynamically add form when button click. I have a nested accordion and inside the accordion is ng-select. To make it clear this is my code
<div class="box box-default" *ngFor="let form of forms; let form_array_index = index">
<div class="box-header with-border text-center">
<h3 class="box-title">
<div class="row">
<div class="col-md-4">
<select2 id="segment" name="segment"
[data]="add_segment"
[width]="293"
[value]="segment_value"
(valueChanged)="changedSegment($event, form_array_index)"
required>
</select2>
</div>
</div>
</h3>
<div class="box-tools pull-right">
</div>
</div>
<div class="box-body">
<div class="row">
<div class="col-md-2">
<label for="category">Values:</label>
<select2 id="category" name="category"
[options]="options"
[data]="add_category"
[width]="293"
[value]="category_value"
(valueChanged)="changedCategory($event, form_array_index)"
required>
</select2>
</div>
</div>
<div class="box-header with-border text-center" *ngIf="cat_value">
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion1" href="#{{ category_current[form_array_index] }}">{{collection_category[form_array_index].category}}
</a>
</h5>
</div>
<div id="{{ category_current[form_array_index] }}" class="panel-collapse collapse">
<div class="panel-body">
<div class="panel-body">
<button class="btn btn-success btn-xs pull-left" (click)="addQuestions()">Add Question</button>
<div class="row" >
<select2 *ngIf="query" id="question" name="question"
[data]="add_question"
[width]="293"
[value]="question_value"
(valueChanged)="changedQuestion($event)"
required>
</select2>
</div>
<button class="btn btn-success btn-xs pull-left" (click)="addSubCat()">Add Sub Category</button>
<div class="row" >
<select2 *ngIf="subcat" id="subcategory" name="subcategory"
[options]="options"
[data]="add_subcategory"
[width]="293"
[value]="subcategory_value"
(valueChanged)="changedSubcategory($event, form_array_index)"
required>
</select2>
</div>
<div class="panel-group" id="accordion21" *ngIf="subcat">
<ul class="list-group">
<li class="list-group-item" >
<div class="panel">
<a data-toggle="collapse" data-parent="#accordion21" href="#{{ subcategory_current }}" >
<strong>{{ get_subcategory }} </strong>
</a>
<div id="{{subcategory_current}}" class="panel-collapse collapse">
<div class="panel-body">
<label for="question">Question:</label>
<select2 id="question" name="question"
[data]="add_question"
[width]="293"
[value]="question_value"
(valueChanged)="changedQuestion($event)"
required>
</select2> <br>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div></div>
</div>
<div class="box-tools pull-right">
</div>
</div>
</div>
This means in SEGMENT it can have multiple CATEGORY and inside category it can have a question or they they Choose SUB CATEGORY and they have to choose a question
This is my component.ts
public collection_category = [];
public collection_subcategory = [];
addSegment(){
this._q_service.addSegment().
subscribe(
data => {
this.add_segment = Array.from(data);
let id = 0;
let text = 'Select Segment';
this.add_segment.unshift({id,text});
// this.segment_value = [];
this.segment_current = this.segment_value;
},
err => console.error(err)
);
}
changedSegment(data: any, form_array_index: any) {
this.segment_current = data.value;
if(this.segment_current.length > 0){
for (let i = 0; i < this.add_segment.length; ++i) {
if (this.add_segment[i].id == this.category_current) {
this.collection_category[form_array_index].segment = this.add_segment[i].text;
}
}
}
console.log('segment', this.collection_category);
}
addCategory(){
this._q_service.addCategory().
subscribe(
data => {
this.add_category = Array.from(data);
this.category_value = [];
this.options = {
multiple: true
}
let id = 0;
let text = 'Select Category';
this.add_category.unshift({id,text});
this.category_value = [];
// this.category_current.push(this.category_value);
// console.log(this.category_current);
},
err => console.error(err)
);
}
changedCategory(data: any, form_array_index: any ) {
this.category_current = data.value;
if(this.category_current.length > 0){
let len = this.add_category.length;
for (let i = 0; i < len; ++i) {
if (this.add_category[i].id == this.category_current) {
this.get_category = this.add_category[i].text;
this.collection_category[form_array_index].category = this.add_category[i].text;
}
}
this.cat_value = true;
}
console.log(this.collection_category);
this.addSubCategory();
this.addQuestion();
}
addSubCategory(){
this._q_service.addSubCategory().
subscribe(
data => {
this.add_subcategory = Array.from(data);
this.subcategory_value = [];
this.options = {
multiple: true
}
let id = 0;
let text = 'Select Sub Category';
this.add_subcategory.unshift({id,text});
this.subcategory_value = [];
this.subcategory_current = this.subcategory_value;
},
err => console.error(err)
);
}
changedSubcategory( data: any, form_array_index: any ) {
this.subcategory_current = data.value;
if(this.subcategory_current.length > 0){
let len = this.add_subcategory.length;
for (let i = 0; i < len; ++i) {
if (this.add_subcategory[i].id == this.subcategory_current) {
this.get_subcategory = this.add_subcategory[i].text;
this.collection_category[form_array_index].subcategory = this.add_subcategory[i].text;
// this.collection_subcategory[form_array_index].subcategory_collection = [];
}
}
this.sub_value = true;
}
}
addQuestion(){
this._q_service.questionList().
subscribe(
data => {
this.add_question = Array.from(data);
this.question_value = [];
let id = 0;
let text = 'Select Question';
this.add_question.unshift({id,text});
this.subcategory_value = ['0'];
this.question_current = this.question_value;
},
err => console.error(err)
);
}
changedQuestion(data: any) {
this.question_current = data.value;
if(this.question_current != 0){
let len = this.add_question.length;
for (let i = 0; i < len; ++i) {
if (this.add_question[i].id == this.question_current) {
this.get_question = this.add_question[i].text;
}
}
}
}
addFormRow(){
let new_form ={
id: '',
segment: '',
category: '',
subcategory: '',
question: ''
};
// this.category_current.push(0);
let segment_categories = {
segment: '',
category: '',
subcategory: '',
question: ''
};
//this.category_current[form_array_index].category
this.collection_category.push(segment_categories);
this.forms.push(new_form);
}
*And every time the user hit the Add Form button it dynamically add form *
But it gives me an error every time I add form the first accordion is not working on the second form but the first form is working well