how to generate the id of a div dynamically using javascript - javascript

I have a (+) sign and a (-) sign. If the user clicks on the + sign than whatever their in the row will automatically get generated the same with new id.
Now when user click on + sign than div id and text box under it will get changed.
Code below for div as follows:
<div class="row" id="Div0">
<div class="col-md-3">
<div class="form-group">
<label for="name">Last Name</label>
<input type="text" class="form-control" id="txtLastName0" placeholder="Enter name" required="required" />
</div>
</div>
<div class="col-md-9"></div>
</div>
Now when user clicks on + sign the new row with text box with new id txtLastName1 will get generated.
Now on click of + sign how do i get new id of textbox and a div with new row.
Div1 and textbox1 will get generated

Basically what you should do is, keep the markup you want to generate as a template in your DOM and when user clicks the "Add" button, clone this markup and append to the DOM (to a container div). then update the Id's of the input and divs as needed.
A simply sample would be like
<div class="row" id="template" style="display: none;">
<div class="col-md-3">
<div class="form-group">
<label for="name">Last Name</label>
<input type="text" class="form-control lname" id="txtLastName"
placeholder="Enter name" required="required" />
</div>
</div>
<div class="col-md-9"></div>
</div>
<button id="btnAdd">+</button>
<div id="container"></div>
Now wire up a click event handler to the Add/+ button. You may use the jQuery clone() method.
$(function () {
$("#btnAdd").click(function(e) {
e.preventDefault();
var childCount = $("#container").children().length;
var c = $("#template").clone().show();
c.attr("id", "Div" + childCount );
c.find(".lname").attr('id', 'txtLastName' + childCount);
$("#container").append(c);
});
});
For deleting, you can add a event handler on the delete button and remove the specific div from dom. jQuery remove() method will do it. Use closest() and find as needed to get the correct div to remove.
Here is a working simple jsbin sample for your reference

Related

How to get id of a dynamic input field in javascript

I want to create a dynamic form where I also apply JavaScript to the dynamic elements.
What I want to do right now is figure out which field (stored in array or whatever data structure) in JavaScript has been clicked so that I can apply the script to that particular field.
The HTML looks like this:
<div class="triple">
<div class="sub-triple">
<label>Category</label>
<input type="text" name="category" id="category" placeholder="Classes/Instances" required/>
<ul class="cat-list"></ul>
</div>
<div class="sub-triple">
<label>Relation</label>
<input type="text" name="relation" id="relation" placeholder="Properties" required/>
<ul class="rel-list"></ul>
</div>
<div class="sub-triple">
<label>Value</label>
<input type="text" name="value" id="value" placeholder="Classes/Instances" required/>
<ul class="val-list"></ul>
</div>
</div>
This "triple" div is dynamic and I want to create as many "triples" as the user wants, that also means the input fields of inside the "triple" section increase as well.
I'm confused on how to add javascript to one element of the input. For example I have inputs: category, relation and value and the user wanted 2 or more triples then the input ids could look like category2, relation2 and value2 or something similar to that.
let category = document.getElementById("category");
category.addEventListener("keyup", (e) => {
removeElements();
listDown(category, sortedClasses, ".cat-list")
});
If I lets say clicked on category2 for instance how do I tell that to my javascript since these fields are completely dynamic.
Summary: The user is adding repeat sections of triples (containing 3 input elements), where the id of each input element is generated dynamically. My script above works for the first triple section only as the ids are fixed, as for successive "triple" section the id of the fields get changed. How do I identify (see which element has been clicked) and get these dynamic ids
Try listening to the parent element and then using the event's target to figure out the identity of the input. Since the child elements events will bubble up you'll be able to listen to all children
e.g.
let parentElement = document.querySelector(".triple");
parentElement.addEventListener("click", (e) => {
console.log(e.target.id);
});
You can use the onfocus event
<div class="triple">
<div class="sub-triple">
<label>Category</label>
<input type="text" name="category" id="category" placeholder="Classes/Instances" onfocus="onFocusCategoryInput()" required/>
<ul class="cat-list"></ul>
</div>
<div class="sub-triple">
<label>Relation</label>
<input type="text" name="relation" id="relation" placeholder="Properties" onfocus="onFocusRelationInput()" required/>
<ul class="rel-list"></ul>
</div>
<div class="sub-triple">
<label>Value</label>
<input type="text" name="value" id="value" placeholder="Classes/Instances" onfocus="onFocusValueInput()" required/>
<ul class="val-list"></ul>
</div>
</div>

How to Remove a Div using variable parameters?

I'm trying to create a way to add entries to my form so that the user can choose how many he wants, but I can't get the remove part working.
JavaScript
var i = 1;
var divContent = document.getElementById('formulario');
//Click to add a field
function cria() {
//This add a HTML Inputs and divs who the ID is variable how the 'i' is increasedf
document.getElementById('formulario').innerHTML += '<div class="mb-1 col-3" id="div'+i+'"><label for="nomeTx0" class="form-label">Nome</label><input type="text" class="form-control" id="nomeTx'+i+'" name="nomeTx'+i+'" required></div><div class="mb-1 col-3" id="div2'+i+'"><label for="taxa'+i+'" class="form-label">Valor</label><input type="float" class="form-control" id="taxa'+i+'" name="taxa'+i+'" required></div>- Remover campo';
i++;
}
function remove(div1, div2){
var div = document.getElementById(div1);
var div2 = document.getElementById(div2);
div.remove();
div2.remove();
i--;
}
And now the HTML
<form>
<h4 class="card-tittle text-center">Taxas</h4>
<div id="formulario" class="form row align-items-start">
<div class="mb-1 col-3" id="0">
<label for="nomeTx0" class="form-label">Nome</label>
<input type="text" class="form-control" id="nomeTx0" name="nomeTx0" required>
</div>
<div class="mb-1 col-3" id="0">
<label for="taxa0" class="form-label">Valor</label>
<input type="float" class="form-control" id="taxa0" name="taxa0" required>
</div>
</div>
+ adicionar campo
<div class="mb-1 col-lg-12" style="text-align: center;">
<button class="btn btn-primary col-5" id="Enviar" type="submit" text="Enviar">Adicionar Taxas</button>
</div>
</form>
ID="taxa"+i but when I call the remove(); error is printed to me saing the variable is null.
This is really not the right approach in the first place.
Your fundamental problem is that you are relying on ids to know what element(s) to add and remove and this is leading you to concatenate an id onto dynamically created elements, made from long strings with variables concatenated into them. In reality, you should avoid ids whenever possible as they make your code very brittle and don't scale well.
This is a perfect use for the HTML <template> element. As you can see from the re-worked code below, all ids have been removed - - you don't need them. Additionally, instead of long strings with a variable concatenated into it, you just need to copy/clone the template whenever you need one. Then, you can use "event delegation" and smartly organized HTML to just set up a single click event on a master wrapper element, where the actual element that was clicked (the event.target) can be checked. If it was a remove button, then just remove the entire wrapper that is the nearest ancestor to the remove button that was clicked.
You can now add and remove as many items as you like with no need for an id or counting variables!
// Get a reference to the template, outer div and the add "button"
const template = document.querySelector("template");
const wrapper = document.querySelector(".wrapper");
const add = document.querySelector(".add");
// Set up the add event in Javascript, not with inline HTML
add.addEventListener("click", function(event){
var clone = template.content.cloneNode(true); // Clone the template
wrapper.appendChild(clone);
});
// Set up a wrapper level click event that any clicks within it will bubble up to
wrapper.addEventListener("click", function(event){
// Test to see if it was remove "button" that was clicked
if(event.target.classList.contains("remove")){
// Just remove the closest ancestor div that holds that particular group
// and remove it.
event.target.closest("div.templateWrapper").remove();
}
});
.mb-1.col-lg-12 {
text-align:center;
}
.mb-1.col-3 {
margin:2px;
}
.add, .remove {
cursor:pointer;
color:blue;
}
.labelName { display:inline-block; width:3em; }
/* This is just to better see the groups */
.templateWrapper, .form {
background-color:aliceblue;
padding:5px;
margin:8px;
}
<!-- This will not initially be shown on the page.
It will be used to copy from when/if needed. -->
<template>
<div class="templateWrapper">
<div class="mb-1 col-3">
<label class="form-label"><span class="labelName">Nome</span>
<input type="text" class="form-control" name="nomeTx" required>
</label>
</div>
<div class="mb-1 col-3">
<label class="form-label"><span class="labelName">Valor</span>
<!-- An input does not have a type=float -->
<input class="form-control" name="taxa" required>
</label>
</div>
<span class="remove">- Remover campo</span>
</div>
</template>
<form>
<h4 class="card-tittle text-center">Taxas</h4>
<!-- Hyperlinks are for navigation, not JavaScript click hooks. Any visible element
supports a click event. Use span and div for generic clickable inline or block
elements that need to have click event handlers. -->
<span class="add">+ adicionar campo</span>
<div class="wrapper">
<div class="form row align-items-start">
<div class="mb-1 col-3">
<label class="form-label"><span class="labelName">Nome</span>
<input type="text" class="form-control" name="nomeTx0" required>
</label>
</div>
<div class="mb-1 col-3">
<label class="form-label"><span class="labelName">Valor</span>
<input type="float" class="form-control" name="taxa0" required>
</label>
</div>
</div>
</div>
<div class="mb-1 col-lg-12">
<!-- A button does not have a "text" attribute -->
<button class="btn btn-primary col-5" type="submit">Adicionar Taxas</button>
</div>
</form>
You would like to pass the ids of the html elements to function remove , instead you pass something else.
Try this:
function remove(d1, d2){
//what are passing to function... id , or something else ?
console.log(d1,d2);
// now I force the arguments passed to function to a valid value id for test
var a = document.getElementById('div1'); // id is div1
var b = document.getElementById('div21'); // id is div21
//Ask to parentNode to remove his child
a.parentNode.removeChild(a);
b.parentNode.removeChild(b);
i--;
}
The problem in your code is that you don't pass a string to the remove function but instead you pass the whole element. That is why document.getElementById can't find anything because it expects a string as a parameter. I refactored you code a bit and also when removing the fields the link - Remover campo stayed and was not deleted. I fixed that as well by passing a third argument to the remove function.
var i = 1;
var divContent = document.getElementById('formulario');
//Click to add a field
function cria() {
//This add a HTML Inputs and divs who the ID is variable how the 'i' is increasedf
document.getElementById('formulario').innerHTML += '<div class="mb-1 col-3" id="div'+i+'"><label for="nomeTx0" class="form-label">Nome</label><input type="text" class="form-control" id="nomeTx'+i+'" name="nomeTx'+i+'" required></div><div class="mb-1 col-3" id="div2'+i+'"><label for="taxa'+i+'" class="form-label">Valor</label><input type="float" class="form-control" id="taxa'+i+'" name="taxa'+i+'" required></div>- Remover campo';
i++;
}
function remove(div1, div2, link){
var div = document.getElementById(div1);
var div2 = document.getElementById(div2);
var link = document.getElementById(link);
divContent.removeChild(div);
divContent.removeChild(div2);
divContent.removeChild(link)
i--;
}
The easiest way to do your code working it change your function "cria". (it's not the best option)
You miss ' '.
You have this.
onclick="remove(div'+i+',div2'+i+')"
You need this.
onclick="remove(\'div'+i+'\',\'div2'+i+'\')"
Javascript just doesn't understand that these parameters are strings.
And the full function "cria" after changes.
function cria() {
//This add a HTML Inputs and divs who the ID is variable how the 'i' is increasedf
document.getElementById('formulario').innerHTML += '<div class="mb-1 col-3" id="div'+i+'"><label for="nomeTx0" class="form-label">Nome</label><input type="text" class="form-control" id="nomeTx'+i+'" name="nomeTx'+i+'" required></div><div class="mb-1 col-3" id="div2'+i+'"><label for="taxa'+i+'" class="form-label">Valor</label><input type="float" class="form-control" id="taxa'+i+'" name="taxa'+i+'" required></div>- Remover campo';
i++;
}

Element created in jQuery not firing the listener

I am little confused with this problem. I am trying to create a dynamic form, in which the used can make as many descriptions, checkboxes and number inputs and he wants. I am just creating a simple dynamic formular with jQuery, and so far I can create elements that they delete themselves (when the user click on remove the field) and I can add more elements in the form.
Code as follows:
<!-- THE FIELD THAT I APPEND IS A COPY OF THIS ITEM -->
<div class="container-field-form" id="description-field">
<div class="container-field-form__img remove">
<img src="/static/svg/problem.svg" class="icon-to-do-form img-zoom-min " id="deleteButton">
</div>
<div class="container-field-form__field form-field">
<textarea onchange="this.value = capitalizeFirstLetter(this.value)" class="form-control form-field" name="description" id="description" rows="3" placeholder="Enter the description"></textarea>
</div>
</div>
<!-- FROM HERE I APPEND AND ONLY APPEARS ONE AT THE BEGGGINING -->
<div class="container-field-form" id="description-field">
<div class="container-field-form__img" id="add-description">
<img src="/static/svg/add-component.svg" class="icon-to-do-form img-zoom-min " id="deleteButton">
</div>
<div class="container-field-form__field form-field">
<textarea onchange="this.value = capitalizeFirstLetter(this.value)" class="form-control form-field" name="description" id="description" rows="3" placeholder="Enter the description"></textarea>
</div>
</div>
The problem that I have here, is that the items that I hardcoded in the HTML, they answer correctly (remove when they need to be removed or duplicate any camp), but with the new items that I add to the HTML, they do not answer to the listener (and it is a exact copy from the html, in the html hardcoded will work with any number, with the html inserted with jQuery no.
Here I give you the jQuery code, that just prepend a copy of the field of the HTML (working with no problem) and that removes the field when we click to remove (removes the current field and works but only in the hardcoded html)
$("#add-description").click(function() {
$("#description-fields").prepend('<div class="container-field-form" id="description-field"><div class="container-field-form__img remove"><img src="/static/svg/problem.svg" class="icon-to-do-form img-zoom-min " id="deleteButton"></div><div class="container-field-form__field form-field"><textarea onchange="this.value = capitalizeFirstLetter(this.value)" class="form-control form-field" name="description" id="description" rows="3" placeholder="Enter the description"></textarea></div></div>')
});
$(".remove").click(function() {
$(this).parent().remove();
});
Am I missing something?
Thanks in advance
you should use
$('html').on("click", "div.remove", function() {
$(this).parent().remove();
});

Having trouble targeting a single input among multiple elements with the same class name (jQuery)

I have a page with a list of li elements, each called .section. The page starts with just one section, but the user can add more with a click. Each section has a dropdown called .wip-location and three input fields called .section-number, .section-name, and .section-description. (The -number and -description inputs are irrelevant but I included them here just in case they are causing problems.)
Every time the dropdown is changed, I'd like the selected text to get filled into the .section-name input.
This works the first time (when there is only one .section, .wip-location, and .section-name on the page), but as soon as the user adds more .sections, it appears that Jquery is unable to figure out which element to act upon, and no inputs are filled.
HTML
<li class="section">
<div class="form-group row">
<label class="col-sm-2 text-sm-right">Section Number</label>
<div class="col-sm-7">
<input class="section-number" type="number" step="0.01" min="1" />
</div>
<label class="col-sm-2 text-sm-right">Section Name</label>
<div class="col-sm-7">
<input class="section-name" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 text-sm-right">Section Description</label>
<div class="col-sm-7">
<textarea class="section-description" />
</div>
<label class="col-sm-2 text-sm-right">WIP Location</label>
<div class="col-sm-7">
#Html.DropDownListFor(m => m.WipLocation,
new SelectList(Model.WipLocations, "Key", "Value"),
"-- select --",
new { #class = "wip-location" })
</div>
</div>
</li>
jQuery
// Automatically add Wip Location choice to Section Name input
$('.wip-location').change(function () {
var $location = $('option:selected', $(this)).text();
var $section = $(this).closest('.section');
var $sectionName = $section.find('.section-name');
$sectionName.val($location);
});
As I said, when there is only one .section and .wip-location on the page, it works perfectly. I suspect jQuery gets confused when there are multiple .wip-locations or something, but I'm not sure if that's really the problem or how to fix it.
Since it is dynamically added you could try to call the event like this:
$(document).on('change', '.wip-location', function(){/*...*/})

JQuery detects focusOut even if I still focus on input inside the same div. How to change it?

This is my code:
Javascript:
$(".test").on("focusout", function (e) {
$("#output").append("Lost focus<br>");
});
HTML:
Inputs inside div:
<div class="test">
<input type="text" />
<input type="text" />
</div><br>
Inputs outside div:<br>
<input type="text" />
<div id="output">
</div>
I want to detect if user leaves "div.test". Unfortunately, "focusout" works also when I move focus to other object inside this div.
Look at this fiddle: http://jsfiddle.net/Piotrek1/wfukje3g/6/
Click on first input and use Tab to switch through textboxes. "
Lost focus" should appear only if user move out from the div, but it happens always. Why is that and how to change it?
The $ operator returns a collection. You have two inputs inside the <div class="test">. So it matches all elements and children with the .test class.
I think what you want two divs with separate input elements and two different classes OR, use an ID on the actual input element so the $ operator only matches the input id you want this event to fire on. http://jsfiddle.net/wfukje3g/7/
$("#test").on("focusout", function (e) {
$("#output").append("Lost focus<br>");
});
<div class="sometest">
<input id="test" type="text" />
<input type="text" />
</div><br>
Inputs outside div:<br>
<input type="text" />
<div id="output">
</div>
I have implemented piece of code to handle div focus out
$(document).ready(function () {
var count = 1;
$("#name").focusout(function (e) {
if($(this).has(e.relatedTarget).length === 0) {
$("#output").append("<label style='width:100%;'>"+ count++ +" Name div focus out </label>");
}
});
});
Inputs inside div:
<div id="name" class="test">
<input type="text" id="firstname"/>
<input type="text" id="lastname"/>
</div>
Inputs outside div:<br>
<input type="text" id="dob"/>
<div id="output" style="width:100%"></div>
In this piece of code I have used relatedTarget.
relatedTarget will provide the next focused element If next element is not the child of this div then it is div focus out.
Try this in your code.
I hope this will be helpful.
Thanks
JSFIDDLE LINK - Sample code

Categories