Clone div not being removed, just the original one - javascript

I have a div being cloned and I would like the button remove to remove the selected div. It's only removing the html div that is used to clone the field.
See my code below:
JS
// Clones Schedule Field
function cloneField(){
const newFieldContainer = document.querySelector(".schedule-item").cloneNode(true)
console.log(newFieldContainer)
let fields = newFieldContainer.querySelectorAll('input')
fields.forEach(function(field){
field.value = ""
})
document.querySelector("#schedule-items").appendChild(newFieldContainer)
}
// Adds new field
function addButton(){
let button = document.querySelector("#add-time")
const selected = document.getElementById('select').selected
let scheduleItems = document.querySelector('#schedule-items')
let inputs = scheduleItems.querySelectorAll('input')
if(selected == true || [...inputs].some(input=>input.value === "")){
alert('Tem o dia ou a hora faltando nos Horários Disponíveis.')
button.removeEventListener('click',cloneField)
}else{
button.addEventListener('click',cloneField)
}
}
// Removed field added if needed
let buttonRemove = document.querySelector('.remove-schedule-item')
buttonRemove.addEventListener('click',removeField)
function removeField(){
let scheduleItem = document.querySelector('.schedule-item')
scheduleItem.parentNode.removeChild(scheduleItem);
console.log('hey')
}
HTML
<fieldset id="schedule-items">
<legend>Horários disponíveis
<button type="button" id="add-time" onclick="addButton()">+Novo horário</button>
</legend>
<div class="schedule-item">
<div class="select-block">
<label for="weekday">Dia da semana</label>
<select name="weekday[]" required="true">
<option id="select" value="select" selected>Selecione uma opção</option>
{%for weekday in weekdays %}
<option value="{{loop.index0}}">{{weekday}}</option>
{%endfor%}
</select>
</div>
<div class="input-block">
<label for="time_from">Das</label>
<input type="time" name="time_from[]" required>
</div>
<div class="input-block">
<label for="time_to">Ate</label>
<input type="time" name="time_to[]" required>
</div>
<div class="remove-schedule-item">
<button>remove</button>
</div>
</div>
</fieldset>
</form>
Thanks in advance

when you try to remove the item
function removeField(){
let scheduleItem = document.querySelector('.schedule-item')
scheduleItem.parentNode.removeChild(scheduleItem);
console.log('hey')
}
you are always selecting the first .schedule-item and then delete the first item
edit:
when you clone you element you need to add event listener to the new element
function cloneField(){
const newFieldContainer = document.querySelector(".schedule-item").cloneNode(true);
let fields = newFieldContainer.querySelectorAll('input')
fields.forEach(function(field){
field.value = ""
});
document.querySelector("#schedule-items").appendChild(newFieldContainer);
const removeBtn = newFieldContainer.querySelector('.remove-schedule-item');
if(removeBtn){
removeBtn.addEventListener('click',function(){
newFieldContainer.remove();
});
}
}

Related

JS: prevent reseting of form fields after adding new form

I have below code where I add new form after clicking button. If I put some values into the fields everything is reseted. I would like to prevent that.
I tried e.preventDefault() and return false but it's not working as I would like to.
Additionally after clicking 'add button' I am taking data from json file.
Please see my code here. Any help will be appreciated.
// add new product to the list
const newLocal = document.querySelector('.add-product-button');
const addNewProduct = newLocal;
const listProduct = document.querySelector('.products-list');
const changeVisibility = document.getElementById('change-visibility');
let productCounter = 1;
addNewProduct.addEventListener('click', e => {
e.preventDefault();
productCounter++;
generateTemplate();
changeVisibility.style.display = 'block';
});
const generateTemplate = (e) => {
const html = `
<li>
<div class="first-product-indicator">
<div class="first-product-border-line"></div>
<div class="product-number">${productCounter}</div>
</div>
<form action="" method="get" class="form-product">
<select name="product-type" id="product-type" class="" required>
<option value="" disabled selected hidden>Typ Produktu</option>
<option value="produkt" >PRODUKT GOTOWY</option>
<option value="materiały" >MATERIAŁY POMOCNICZE</option>
<option value="surowce" >SUROWCE</option>
</select>
<div class="product-container">
<select name="product" id="product" class="option-field product-list" required>
<option value="" disabled selected hidden>Produkt</option>
</select>
<i class="fas fa-plus-circle add-product"></i>
</div>
<div class="form-price">
<input type="number" id="quantity" name="quantity" placeholder="Ilość">
<input type="number" id="netto" name="netto" placeholder="Netto">
<input type="number" id="brutto" name="brutto" placeholder="Brutto">
</div>
<div class="form-total-price">
<input type="number" id="netto-total" name="netto-total" placeholder="Wartość netto">
<input type="number" id="brutto-total" name="brutto-total" placeholder="Wartość brutto">
</div>
</form>
</li>
`;
listProduct.innerHTML += html;
// populate product select field with values from json file (finished_good.json)
let newProductElement = document.querySelector('.products-list').lastElementChild;
let dropdownProductAdd = newProductElement.querySelector('.product-list');
dropdownProductAdd.length = 0;
let defaultOptionProductAdd = document.createElement('option');
defaultOptionProductAdd.text = 'Produkt';
dropdownProductAdd.add(defaultOptionProductAdd);
dropdownProductAdd.removeIndex = 0;
const urlProductAdd = 'finished_good.json';
const requestProductAdd = new XMLHttpRequest();
requestProductAdd.open('GET', urlProductAdd, true);
requestProductAdd.onload = function() {
if (requestProductAdd.status === 200) {
const dataProductAdd = JSON.parse(requestProductAdd.responseText);
let optionProductAdd;
for (let i = 0; i < dataProductAdd.length; i++) {
optionProductAdd = document.createElement('option');
optionProductAdd.text = dataProductAdd[i].name;
dropdownProductAdd.add(optionProductAdd);
}
} else {
// Reached the server, but it returned an error
}
}
requestProductAdd.onerror = function() {
console.error('An error occurred fetching the JSON from ' + urlProductAdd);
};
requestProductAdd.send();
e.preventDefault();
};

PHP code doesn't see input added through js

I have form that collect datas when SAVE button is pressed from three inputs. First two is already loaded on the site, but last appears when DVD-disk is selected in <select>. So PHP code see values from first two inputs, but not from the last one. I added name and id to all of them. Inputs are in the main container that is in form.
Expected output: echo ($DVDdisk) show data
Real output: Undefined index: DVDsize
let selector = document.getElementById("selector");
let main = document.getElementById("input-main-add");
let div = document.createElement('div');
let h2 = document.createElement('H2');
let input = document.createElement('input');
selector.addEventListener("change", (e) => {
if (selector.value == "DVD") {
div.classList.add('input-add-holder');
main.appendChild(div);
h2.textContent = 'Enter size:';
h2.style.display = 'inline-block';
div.appendChild(h2);
input.setAttribute("name", "DVDsize");
input.setAttribute("id", "DVDsize");
div.appendChild(input);
}
});
<form method="POST" action="add.php">
<button class="accept-btn" type="submit">SAVE</button>
<!-- + -->
<button class="decline-btn">CANCEL</button>
<!-- + -->
</div>
</div>
<div class="input-main-add" id="input-main-add">
<!-- + -->
<div class="input-add-holder">
<H2 style="display:inline-block">SKU: </H2>
<input class="something" name="SKU" id="SKU"></input>
</div>
<div class="input-add-holder">
<H2 style="display:inline-block">Name: </H2>
<input class="something" name="name" id="name"></input>
</div>
<div class="input-add-holder">
<H2 style="display:inline-block">Type Switcher: </H2>
<select name="selector" id="selector">
<option value="DVD" id="DVD" name="DVD">DVD-Disk</option>
<option value="book" id="book" name="book">Book</option>
<option value="furniture" id="furniture" name="furniture">Furniture</option>
</select>
</div>
</div>
</form>
PHP code:
<?php
$SKU = $_POST["SKU"];
$name = $_POST["name"];
$DVDsize = $_POST["DVDsize"];
echo ($SKU);
echo ($name);
echo ($DVDsize);
?>
Your JS listen for change event on Type Switcher select box that the selected value must be DVD-Disk but your default value of this select box is DVD-Disk which is already selected.
So, this event will never happens when you just load the page, fill form (without change select box) and submit.
If this event never happens, it means input name DVDSize will not rendered and not send to server. That's why your PHP doesn't see this input.
You have to manually trigger change event for select box once DOM ready.
let selector = document.getElementById("selector");
let main = document.getElementById("input-main-add");
let div = document.createElement('div');
let h2 = document.createElement('H2');
let input = document.createElement('input');
selector.addEventListener("change", (e) => {
if (selector.value == "DVD") {
div.classList.add('input-add-holder');
main.appendChild(div);
h2.textContent = 'Enter size:';
h2.style.display = 'inline-block';
div.appendChild(h2);
input.setAttribute("name", "DVDsize");
input.setAttribute("id", "DVDsize");
div.appendChild(input);
}
});
// manually trigger change event.
let selectTypeSwitcher = document.getElementById('selector');
if (selectTypeSwitcher) {
selectTypeSwitcher.dispatchEvent(new Event('change'));
}
<form method="POST" action="add.php">
<button class="accept-btn" type="submit">SAVE</button>
<!-- + -->
<button class="decline-btn">CANCEL</button>
<!-- + -->
</div>
</div>
<div class="input-main-add" id="input-main-add">
<!-- + -->
<div class="input-add-holder">
<H2 style="display:inline-block">SKU: </H2>
<input class="something" name="SKU" id="SKU"></input>
</div>
<div class="input-add-holder">
<H2 style="display:inline-block">Name: </H2>
<input class="something" name="name" id="name"></input>
</div>
<div class="input-add-holder">
<H2 style="display:inline-block">Type Switcher: </H2>
<select name="selector" id="selector">
<option value="DVD" id="DVD" name="DVD">DVD-Disk</option>
<option value="book" id="book" name="book">Book</option>
<option value="furniture" id="furniture" name="furniture">Furniture</option>
</select>
</div>
</div>
</form>
Run the code above while open network inspector and you will see DVDSize input send to the server.

Fields Added Via Javascript not posting Data into $POST

I have created a form which can be dynamically changed using the buttons included. These buttons allow for more input fields to be added/removed. The issue is that the input fields created are not posting any data/ Values in those fields not being added to the $POST array on the submit of the form.
The main functions below resposible for adding and removing rows is RemoveRows() and addRows()
What should happen is that on submit all values in the form should be "posted" then I can access all of those fields via $_POST["nameOfField"].
The way I have currently approached this is to create an input fields with the relevant id's and names then append that field to where the "hard coded" fields exists.
From my initial debugging none of the fields that have been added via javascript are in $Post which I have checked via var_dump($_REQUEST);
I have also seen that the nodes that are added are not elements of the form tag even though the nodes are added between the opening and closing tag. This can be seen in the doBeforeSubmit() Function where we can see all elements that are children of the and this never changes as rows are added/removed.
function showPlatforms() {
let nacellesOptions = ["Option1", "option2", "Option3"];
let milOptions = ["Option1", "option2", "Option3"]
let highOptions = ["Option1", "option2", "Option3"]
let entry = document.getElementById("vs")
let platfom = document.getElementById("platform")
if (platform.hasChildNodes()) {
var lastChild = platfom.lastElementChild
while (lastChild) {
platfom.removeChild(lastChild)
lastChild = platform.lastElementChild
}
}
if (entry.value == "Nacelles") {
for (var i = 0; i < 2; i++) {
var option = document.createElement("option");
option.value = nacellesOptions[i]
option.innerHTML = nacellesOptions[i]
platform.appendChild(option)
}
} else if (entry.value == "Military") {
for (var i = 0; i < 2; i++) {
var option = document.createElement("option");
option.value = milOptions[i]
option.innerHTML = milOptions[i]
platform.appendChild(option)
}
} else {
for (var i = 0; i < 2; i++) {
var option = document.createElement("option");
option.value = highOptions[i]
option.innerHTML = highOptions[i]
platform.appendChild(option)
}
}
}
function formOptions() {
let entry = document.getElementById("type")
if (entry.value == "Engineering MAM") {
document.getElementById("WBS").disabled = false
document.getElementById("Desc").disabled = false
document.getElementById("ProName").disabled = false
} else {
document.getElementById("WBS").disabled = true
document.getElementById("Desc").disabled = true
document.getElementById("ProName").disabled = true
}
}
function formoptions2() {
let entry2 = document.getElementById("organisation")
if (entry2.value == "Aftermarket") {
document.getElementById("COT").disabled = false
document.getElementById("COC").disabled = false
} else {
document.getElementById("COT").disabled = true
document.getElementById("COC").disabled = true
}
}
count = document.getElementById("partNum").childElementCount
function addRows() {
rowNames = ["partNum", "partDesc", "leadTime", "quantity", "dateReq", "unitCost", "unitExtention", "unitSaleValue", "estSalesValue"]
rowNames.forEach(addRow, count)
count = document.getElementById("partNum").childElementCount
//doBeforeSubmit()
}
function doBeforeSubmit() {
var es = document.getElementById("form").elements;
var l = es.length;
var msgs = [];
for (var idx = 0; idx < l; idx++) {
var e = es[idx];
msgs.push('name=' + e.name + ', type=' + e.type + ', value=' + e.value);
}
alert(msgs.join('\n'));
return false;
}
function addRow(id) {
let col = document.getElementById(id)
var box = document.createElement("INPUT")
box.setAttribute("type", "text")
box.setAttribute("id", id + count)
box.setAttribute("name", id + count)
box.setAttribute("class", "form-control")
col.appendChild(box)
}
function RemoveRows() {
rowNames = ["partNum", "partDesc", "leadTime", "quantity", "dateReq", "unitCost", "unitExtention", "unitSaleValue", "estSalesValue"]
rowNames.forEach(removeBoxes)
count = document.getElementById("partNum").childElementCount
}
function removeBoxes(item) {
let box = document.getElementById(item)
let last = box.lastChild
box.removeChild(last)
}
function checkData() {
// if all stuff is correct do this:
document.getElementById("submit").disabled = false
// else dont activate the submit button.
}
<form method="post" id="form" action="SubmitMAM.php">
<div class="row" id="productRow" style="width:95%; margin:auto">
<div id="partNo" class="col-2">
<h3>Part Number:</h3>
</div>
<div class="col-2">
<h3>Part Description:</h3>
</div>
<div class="col-1">
<h3>Lead Time:</h3>
</div>
<div class="col-1">
<h3>Quantity:</h3>
</div>
<div class="col-1">
<h3>Date Required:</h3>
</div>
<div class="col-1">
<h3>Unit Cost:</h3>
</div>
<div class="col-2">
<h3>Unit Cost Extension:</h3>
</div>
<div class="col-1">
<h3>Unit Sale Value:</h3>
</div>
<div class="col-1">
<h3>Est Sales Value:</h3>
</div>
</div>
<div class="row" id="productRow" style="width:95%; margin:auto">
<div id="partNum" class="col-2">
<input type="text" id="partNum0" class="form-control" name="partNum0">
</div>
<div id="partDesc" class="col-2">
<input type="text" id="partDesc0" class="form-control" name="partDesc0">
</div>
<div id="leadTime" class="col-1">
<input type="text" id="leadTime0" class="form-control" name="leadTime0">
</div>
<div id="quantity" class="col-1">
<input type="text" id="quanitity0" class="form-control" name="quantity0">
</div>
<div id="dateReq" class="col-1">
<input type="text" id="dateReq0" class="form-control" name="dateReq0">
</div>
<div id="unitCost" class="col-1">
<input type="text" id="unitCost0" class="form-control" name="unitCost0">
</div>
<div id="unitExtention" class="col-2">
<input type="text" id="unitExtention0" class="form-control" name="unitExtention0">
</div>
<div id="unitSaleValue" class="col-1">
<input type="text" id="unitSaleValue0" class="form-control" name="unitSaleValue0">
</div>
<div id="estSalesValue" class="col-1">
<input type="text" id="estSalesValue0" class="form-control" name="estSalesValue0">
</div>
<button onclick="addRows()" class="btn btn-primary" type="button">Add a Product</button>
<button onclick="RemoveRows()" class="btn btn-primary" type="button">Remove Row</button>
<button onclick="checkData()" class="btn btn-primary" type="button">Check Data</button>
<br>
<button type="submit" name="submit" id="submit" class="btn btn-primary" disabled>Submit</button>
</form>
PHP:
<?php
var_dump($_REQUEST)
?>
UPDATE:
The code has been changed to use a php array by adding square brackets into the name which produces the following html:
<input type="text" id="partNum0" class="form-control" name="partNum[]">
<input type="text" id="partNum1" name="partNum[]" class="form-control">
<input type="text" id="partNum2" name="partNum[]" class="form-control">
You just need to use the name property of the input and add [] at the end, as GrumpyCrouton said. PHP parse it as an array, and you can access it as:
$partNum = $_POST["partNum"];
FIXED: It turns out the above code did not have any issues with the logic or the way it should work, in the source code in visual studio the indentation of some of the Divs was off causing the browser to have issues in rendering the form correctly hence why the added boxes were not included in the form and their values not POSTED.
As a heads up to anyone with maybe a similar issue, it pays to have your code neat.

Input search through an array

well I'm pretty new in Javascript and I would like to improve the following code
that I made to order the buttons based on the search,I don't know that else should I add to make it work so this is what I've done until now, every comment or suggestion will be welcome
Thanks a lot!
//Variables
let valorBusqueda = document.querySelector('#valor');
let opcBusqueda = document.querySelector('.opc-busqueda');
//Event Listener
valorBusqueda.addEventListener('keyup', keyUpCampo);
//Funciones
function keyUpCampo() {
//Muestra el menu de sugerencias
opcBusqueda.style = "display: flex; flex-direction:column; width:165px";
sendToPage();
}
var sendToPage = function () {
//Get the input value by finding the element by its ID
let busqueda = document.getElementById('valor').value;
//Check if the value is in the array
var sugerencias = ['marvel','maravilloso', 'futbol','goku ssj','falafel','robocop', 'rick','ricardo', 'morty', 'x-men', 'starwars', 'goku', 'bulma', 'vegeta', 'simpsons', 'homer', 'cartoon'];
var coincidencias =[]
for (indice in sugerencias) {
let lSug = sugerencias[indice].charAt();
if (lSug.includes(busqueda.charAt())) {
coincidencias.push(sugerencias[indice]);
opcBusqueda.innerHTML = `<input type="button" value=${coincidencias[0]} >
<input type="button" value=${coincidencias[1]} >
<input type="button" value=${coincidencias[2]} >
`
}
}
}
<body>
<div class="busqueda">
<div class="inputs">
<input id="valor" type="text" placeholder=" Busca hashgtags, temas, busca lo que quieras..">
</div>
</div>
<div class="opc-busqueda" style="display: none;">
</div>
</body>

Array of html inputs

I have a html form, where user need to enter the name and address of their office. The number of offices are dynamic.
I want to add an Add More button, so that users can enter the details of any number of offices.
My question is, how can I create an array of inputs where new elements can be added and removed using JavaScript. Currently, I'm doing it using js clone method, but I want an array, so that input data can easily be validated and stored to database using Laravel.
What I'm currently doing..
This is my HTML form where users have to enter the address of their clinic or office. I've taken a hidden input field and increasing the value of that field whenever a new clinic is added, so that I can use loop for storing data.
<div class="inputs">
<label><strong>Address</strong></label>
<input type="text" class="hidden" value="1" id="clinicCount" />
<div id="addresscontainer">
<div id="address">
<div class="row" style="margin-top:15px">
<div class="col-md-6">
<label><strong>Clinic 1</strong></label>
</div>
<div class="col-md-6">
<button id="deleteclinic" type="button" class="close deleteclinic"
onclick="removeClinic(this)">×</button>
</div>
</div>
<textarea name="address1" placeholder="Enter Clinic Address" class="form-control"></textarea>
<label class="text-muted" style="margin-top:10px">Coordinates (Click on map to get coordinates)</label>
<div class="row">
<div class="col-md-6">
<input class="form-control" id="latitude" type="text" name="latitude1" placeholder="Latitude" />
</div>
<div class="col-md-6">
<input class="form-control" id="longitude" type="text" name="longitude1" placeholder="Longitude" />
</div>
</div>
</div>
</div>
</div>
<div class="text-right">
<button class="btn btn-success" id="addclinic">Add More</button>
</div>
And my js code..
function numberClinic(){
//alert('test');
var i=0;
$('#addresscontainer > #address').each(function () {
i++;
$(this).find("strong").html("Clinic " + i);
$(this).find("textarea").attr('name','name'+i);
$(this).find("#latitude").attr('name','latitude'+i);
$(this).find("#longitude").attr('name','longitude'+i);
});
}
$("#addclinic").click(function(e){
e.preventDefault();
$("#addresscontainer").append($("#address").clone());
numberClinic();
$("#addresscontainer").find("div#address:last").find("input[name=latitude]").val('');
$("#addresscontainer").find("div#address:last").find("input[name=longitude]").val('');
$("#clinicCount").val(parseInt($("#clinicCount").val())+1);
});
function removeClinic(address){
if($("#clinicCount").val()>1){
$(address).parent('div').parent('div').parent('div').remove();
$("#clinicCount").val(parseInt($("#clinicCount").val())-1);
}
numberClinic();
}
This way, I think I can store the data to the database but can't validate the data. I'm using the laravel framework.
One way you could do this is by using the position of the input in the parent as the index in the array, then saving the value in the array every time each input is changed. Then you can just add and remove inputs.
Sample code:
var offices = document.getElementById('offices');
var output = document.getElementById('output');
var data = [];
var i = 0;
document.getElementById('add').addEventListener('click', function() {
var input = document.createElement('input');
input.setAttribute('type', 'text');
input.setAttribute('placeholder', 'Office');
var button = document.createElement('button');
var index = i++;
input.addEventListener('keyup', function() {
for (var i = 0; i < offices.children.length; i++) {
var child = offices.children[i];
if (child === input) {
break;
}
}
// i is now the index in the array
data[i] = input.value;
renderText();
});
offices.appendChild(input);
});
document.getElementById('remove').addEventListener('click', function() {
var children = offices.children;
if (children.length === data.length) {
data = data.splice(0, data.length - 1);
}
offices.removeChild(children[children.length - 1]);
renderText();
});
function renderText() {
output.innerHTML = data.join(', ');
}
JSFiddle: https://jsfiddle.net/94sns39b/2/

Categories