Losing Styling When Dynamically Adding New Items Onclick - javascript

I have code that displays a table row with 2 inputs styled using jquerymobile.
I'm using jquery to dynamically add rows when a "plus" button is clicked.
The problem:
When I append a row the static items retain their styling, but the appended row isn't styled.
What am I doing wrong?
Here's the code:
http://jsfiddle.net/Trident/o9r4csc9/
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.1/jquery.mobile-1.2.1.min.css" />
<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="http://code.jquery.com/mobile/1.2.1/jquery.mobile-1.2.1.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
</head>
<body>
<div data-role="page">
<div data-role="header">
<h1>Test</h1>
</div>
<!-- /header -->
<div data-role="content">
<div class="input_fields_wrap">
<table width="100%" border="0" cellspacing="5" cellpadding="5">
<tr>
<td width="180px">Entry price</td>
<td>Percent of position</td>
</tr>
<tr>
<td width="180px"><input type="number" name="entryprice" size="5" min="0" placeholder="100"></td>
<td><input type="range" name="slider-fill" id="slider-fill" value="10" min="0" max="100" data-highlight="true" /></td>
</tr>
<tr>
<td width="180px"><input type="number" name="entryprice" size="5" min="0" placeholder="100"></td>
<td><input type="range" name="slider-fill" id="slider-fill" value="10" min="0" max="100" data-highlight="true" /></td>
</tr>
</table>
</div>
<div align="left">
<button class="add_field_button" data-icon="plus" data-inline="true" >Add</button>
</div>
<!-- When "Add" is clicked, execute python script -->
</div>
<!-- /content -->
</div>
<!-- /page -->
<script language="javascript">
<!-- adds or deletes input fields dynamically -->
$(document).ready(function() {
var max_fields = 1000; //maximum input boxes allowed
var wrapper = $(".input_fields_wrap"); //Fields wrapper
var add_button = $(".add_field_button"); //Add button ID
var addline = '<tr>\
<td width="180px"><input type="number" name="entryprice" size="5" min="0" placeholder="100"></td>\
<td><input type="range" name="slider-fill" id="slider-fill" value="10" min="0" max="100" data-highlight="true" /></td>\
</tr>';
var x = 1; //initlal text box count
$(add_button).click(function(e){ //on add input button click
e.preventDefault();
if(x < max_fields){ //max input box allowed
x++; //text box increment
$(wrapper).append(addline); //add input box
}
});
$(wrapper).on("click",".remove_field", function(e){ //user click on remove text
e.preventDefault(); $(this).parent('div').remove(); x--;
})
});
</script>
</body>
</html>

In JQuery mobile you can manually update dynamic content by the following code:
$(wrapper).trigger('create');
Just one line and all done.
Note: You have to add jquery script for this. I have added it + the css. Please update the UI issue by your self. The point is that the style is working.
http://jsfiddle.net/o9r4csc9/9/
Happy coding :)

In the fiddle you are appending the new table rows into the containing div rather than the table. Change your wrapper variable to reference the table instead.
var wrapper = $(".input_fields_wrap table"); //Fields wrapper
Your rows are recieving jquery-ui styling dynamically, which you haven't included in your 'addrow' html.
A better way would be to clone another row's html, in your case the best would be the last row.
var addline = wrapper.find('tr').last();
And then change the appending line:
$(wrapper).append(addline.clone()); //add input box

I changed a couple of lines in your code:
The first one to append the table row to the table, not the wrapping div
var wrapper = $(".input_fields_wrap table"); //Fields wrapper
And the second one to get the right HTML, now and in the future
var addline = wrapper.find('tr:last')[0].outerHTML;

I have modify your html as required at
http://jsfiddle.net/o9r4csc9/6/
Changes :
1. ID at table <br>
2. Append Row to Table not at div <br>
3. Few css added <br>

i have modified your script section and test on http://jsfiddle.net/o9r4csc9/12/ please change your code as below
$(document).ready(function() {
var max_fields = 1000; //maximum input boxes allowed
var wrapper = $(".input_fields_wrap"); //Fields wrapper
var add_button = $(".add_field_button"); //Add button ID
var addline = '<tr>\
<td width="180px"><input class="ui-input-text ui-body-c ui-corner-all ui-shadow-inset" name="entryprice" size="5" min="0" placeholder="100" type="number"></td>\
<td><input class="ui-input-text ui-body-c ui-corner-all ui-shadow-inset ui-slider-input" name="slider-fill" id="slider-fill" value="10" min="0" max="100" data-highlight="true" data-type="range" type="number"><div class="ui-slider ui-btn-down-c ui-btn-corner-all" role="application"><div style="width: 10%;" class="ui-slider-bg ui-btn-active ui-btn-corner-all"></div><a style="left: 10%;" aria-labelledby="slider-fill-label" title="10" aria-valuetext="10" aria-valuenow="10" aria-valuemax="100" aria-valuemin="0" role="slider" data-theme="c" data-wrapperels="span" data-iconshadow="true" data-shadow="true" data-corners="true" class="ui-slider-handle ui-btn ui-btn-up-c ui-shadow ui-btn-corner-all" href="#"><span class="ui-btn-inner ui-btn-corner-all"><span class="ui-btn-text"></span></span></a></div></td>\
</tr>';
var x = 1; //initlal text box count
$(add_button).click(function(e){ //on add input button click
e.preventDefault();
if(x < max_fields){ //max input box allowed
x++; //text box increment
$(wrapper).find("table").append(addline); //add input box
}
});
$(wrapper).on("click",".remove_field", function(e){ //user click on remove text
e.preventDefault(); $(this).parent('div').remove(); x--;
})
});

Related

Remove form field javascript

I have a form where I have a table with an employee and every time I click on plus a new row for employee is added but when I click the remove field the script add a new row till the maximum. So what I want is the "-" icon to remove the field added.
This is what I came up with so far ...
$(document).ready(function () {
// Input fields increment limitation
var maxField = 3;
// Add button selector
var addButton = $('.add_button');
// Input field wrapper
var emp = $('#employee_tbl');
// New input field html
var fieldHTML = '<tr><td><label for="employee"><i class="fas fa-minus-circle"></i></label><input type="text" name="employee" class="remove_button" id="employee" required></td></tr>';
// Initial field counter is 1
var x = 1;
// Once add button is clicked
$(addButton).click(function () {
// Check maximum number of input fields
if (x < maxField) {
// Increment field counter
x++;
// Add field html
$(emp).append(fieldHTML);
}
});
// Once remove button is clicked
$(emp).on('click', '.remove_button', function (e) {
e.preventDefault();
// Remove field html
$(this).parent('div').remove();
// Decrement field counter
x--;
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet"/>
<table id="employee_tbl">
<tr>
<th>
<b><span data-i18n-key="employee">Employee</span></b>
</th>
</tr>
<tr>
<td>
<label for="employee"><i class="fas fa-plus-circle"></i></label>
<input type="text" name="employee" class="add_button" id="employee" required/>
</td>
</tr>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You're removing parent('div') while there is no one. Use closest('tr') instead.
Also, you had classes add_button and remove_button on wrong elements.
And id should be unique in HTML.
$(document).ready(function () {
// Input fields increment limitation
var maxField = 3;
// Add button selector
var addButton = $('.add_button');
// Input field wrapper
var emp = $('#employee_tbl');
// New input field html
var fieldHTML = '<tr><td><label for="employee"><i class="fas fa-minus-circle remove_button"></i></label><input type="text" name="employee" required></td></tr>';
// Initial field counter is 1
var x = 1;
// Once add button is clicked
$(addButton).click(function () {
// Check maximum number of input fields
if (x < maxField) {
// Increment field counter
x++;
// Add field html
$(emp).append(fieldHTML);
}
});
// Once remove button is clicked
$(emp).on('click', '.remove_button', function (e) {
e.preventDefault();
// Remove field html
$(this).closest('tr').remove();
// Decrement field counter
x--;
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet"/>
<table id="employee_tbl">
<tr>
<th>
<b><span data-i18n-key="employee">Employee</span></b>
</th>
</tr>
<tr>
<td>
<label for="employee"><i class="fas fa-plus-circle add_button"></i></label>
<input type="text" name="employee" required/>
</td>
</tr>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
First of all the OP needs to sanitize the HTML structure.
What is currently used is too complex and constantly at risk of becoming invalid markup due to how the label-control relationship gets handled. The "label for="<id>"" management is not needed especially since with this kind of structure one always is in danger of providing identical id values.
Thus the first change provides a generic id agnostic structure ...
<tr>
<td>
<label for="employee"><i class="fas fa-plus-circle"></i></label>
<input type="text" name="employee" class="add_button" id="employee" required/>
</td>
</tr>
... changes to ...
<tr>
<td>
<label>
<i class="fas fa-plus-circle add_button"></i>
<input type="text" name="employee" required/>
</label>
</td>
</tr>
... and for all removable rows to ...
<tr>
<td>
<label>
<i class="fas fa-minus-circle remove_button"></i>
<input type="text" name="employee" required/>
</label>
</td>
</tr>
Looking into the above two code blocks one also might notice the class-name changes of 'add_button' and 'remove_button' to where both really belong to ... each to its iconized add/remove element.
Thus, the only necessary JavaScript/jQuery code change needs to take place within the remove handler. Since the OP already takes advantage of event delegation, one just has to access the event object's target reference. From there one queries the closest </tr> element which then gets removed.
Prove ...
$(document).ready(function () {
// Input fields increment limitation
var maxField = 3;
// Add button selector
var addButton = $('.add_button');
// Input field wrapper
var emp = $('#employee_tbl');
// New input field html
var fieldHTML = `
<tr>
<td>
<label>
<i class="fas fa-minus-circle remove_button"></i>
<input type="text" name="employee" required/>
</label>
</td>
</tr>`;
// Initial field counter is 1
var x = 1;
// Once add button is clicked
$(addButton).click(function () {
// Check maximum number of input fields
if (x < maxField) {
// Increment field counter
x++;
// Add field html
$(emp).append(fieldHTML);
}
});
// Once remove button is clicked
$(emp).on('click', '.remove_button', function (evt) {
evt.preventDefault();
// Remove field html
$(evt.target).closest('tr').remove();
// Decrement field counter
x--;
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet"/>
<table id="employee_tbl">
<tr>
<th>
<b><span data-i18n-key="employee">Employee</span></b>
</th>
</tr>
<tr>
<td>
<label>
<i class="fas fa-plus-circle add_button"></i>
<input type="text" name="employee" required/>
</label>
</td>
</tr>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Use maskMoney in input that is created dynamic

In the form that opens by default the function in js works well.
But then in the form I have the possibility to create more fields dynamically, but in those fields that you create dynamically it doesn't work.
Let me explain.
Code:
$(document).ready(function() {
var max_fields = 10; //maximum input boxes allowed
var wrapper = $(".input_fields_wrap"); //Fields wrapper
var add_button = $(".add_field_button"); //Add button ID
var x = 1; //initlal text box count
$(add_button).click(function(e) { //on add input button click
e.preventDefault();
var length = wrapper.find("input:text").length;
if (x < max_fields) { //max input box allowed
x++; //text box increment
$(wrapper).append('<div id="teste"><div class="form-group col-md-2"><input type="text" class="form-control1 Preco" name="Valor[]" value="0.00" /><span class="form-highlight">$</span><span class="form-bar"></span><label class="label1" for="Valor">Valor</label></div><button class="remove_field" style="background-color: #313348;"><span class="fa fa-trash fa-fw" aria-hidden="true"></span></button></div>');
}
});
$(wrapper).on("click", ".remove_field", function(e) { //user click on remove text
e.preventDefault();
$("#teste").remove();
x--;
})
});
$(function() {
$('.Preco').maskMoney({ decimal: '.', thousands: ' ', precision: 2 });
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-maskmoney/3.0.2/jquery.maskMoney.min.js"></script>
<button class="btn btn-warning caixa add_field_button" style="float:right;"><i class="fa fa-plus-square fa-5x taman" aria-hidden="true"></i></button>
<div class="input_fields_wrap">
<div class="form-group col-md-2">
<input type="text" class="form-control1 Preco" name="Valor[]" value="0.00" required>
<span class="form-highlight">$</span>
<span class="form-bar"></span>
<label class="label1" for="Valor">Valor</label>
</div>
</div>
As I show in the example the first input works correctly, but when I create a dynamic input it lets the maskMoney function work
$(document).ready(function() { and $(function() { are the same thing. (This is mentioned in the jQuery documentation for .ready()) Because of that, you've essentially declared two onready handlers. onready handlers can happen in any order.
Combine them into one onready handler and order the contents such that the call to maskMoney happens last.

Fill input with max value on click

I'm currently trying to find a way to fill the max value of an input according to the
max="#value"
Currently I'm using asp.net mvc, I'm getting data from a datatable and I render this information inside a html table where in my tr> /tr> I have a td> /td> that looks like this
<td align="center"><input type="number" name="txtID" class="txtID" oninput="setValueAttr(this)" min="0" max="#monto.Trim()" value="" step="any" style="width: 100px" /></td>1
Can anyone tell me how to make a javascript function that automatically fills the max="" value inside a Html TableRow?
The problem is that each row has its unique max #value
Assume the following HTML:
<td align="center">
<input type="number" name="txtID" class="txtID" oninput="setValueAttr(this)" min="0" max="#monto.Trim()" value="" step="any" style="width: 100px" />
<button class="set-max">Max value</button>
</td>
You can add an event listener on the button via JavaScript e.g. put this code in the bottom of your table or in the bottom of the <body> tag.
<script>
var buttons = document.querySelectorAll('.set-max');
buttons.forEach(function (button) {
button.addEventListener('click', function (event) {
var input = event.currentTarget.parentElement.querySelector('input[type="number"]');
input.value = input.max;
});
};
<script>
If the button ends up somewhere else you'd need to adjust the event listener to find the actual target element by navigating through the DOM hierarchy

Adding new input using Jquery breaks tooltips

I'm writing a form and I have to let the user add as many rows as required.
As you can see, my inputs are treated as arrays to later save the data to the DB. (That will be another new thing to me)
$(document).ready(function() {
var maxField = 10; //Input fields increment limitation
var addButton = $('.add_button'); //Add button selector
var wrapper = $('.field_wrapper'); //Input field wrapper
var fieldHTML = '<tr> <td><input type="text" id="NombreProyecto" name="NombreProyecto[]"></td> <td><input type="text" id="Descripcion" name="Descripcion[]"></td> <td><input type="text" id="AplicacionesProyecto" name="AplicacionesProyecto[]"></td> <td style="width: auto"> <div class="range-field "> <input type="range" name="NivelTRL[]" min="1" value="1" max="9" /> </div> </td> </tr>'; //New input field html
var x = 1; //Initial field counter is 1
//Once add button is clicked
$(addButton).click(function() {
//Check maximum number of input fields
if (x < maxField) {
x++; //Increment field counter
$(wrapper).append(fieldHTML); //Add field html
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<div class="step-content">
<div class="container">
<div id="table" class="table-editable ">
<table class="table field_wrapper">
<tr>
<th>Nombre</th>
<th>DescripciĆ³n</th>
<th>Aplicaciones</th>
<th>Nivel TRL</th>
<th><i class="material-icons">add</i>
</th>
</tr>
<tr class="">
<td><input type="text" id="NombreProyecto" name="NombreProyecto[]"></td>
<td><input type="text" id="Descripcion" name="Descripcion[]"></td>
<td><input type="text" id="AplicacionesProyecto" name="AplicacionesProyecto[]"></td>
<td>
<div class="range-field">
<input type="range" name="NivelTRL[]" min="1" value="1" max="9" />
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
</body>
</html>
Everything looks perfect but when the user adds a new row and interacts with the range input, this won't feedback the user about the value he/she is picking.
Just the original one will have the tooltip.
After some testing, it even affects the 'tooltipped' class used to, well, show tooltips over any element.
This is the codepen, It's all ready to show you the problem
How to reproduce it:
In the codepen provided, you will see the blue cross, when you click on it a new row will be added.
Play around with the first range input, it will show you the value on the tooltip.
In the later added range input, it wont.
Thank you for reading, have a nice day.
You should reinit your range elements.
Simply add this code
M.Range.init($('input[type=range]'));
after this
$(wrapper).append(fieldHTML); //Add field html
First, it's not a tooltip on that range input... It's the Materialize nouiSlider effect. So you have to initialyse this on the new element.
M.Range.init(element);
By the way, I did not found this specific is the documentation about range... But I got inspired by this other initialisation example.
CodePen updated

jQuery remove too many fields

I am creating a form where the user can add fields one after the other. For each field I am setting a "remove" button. Each field is in a table, so I give a random id to the table, and pass this id to a removing function doing: $(random-id).remove().
The strange thing is that jQuery is removing all of the tables created by the user, as if the id is not taken into account
Why that can be?
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<script>
function delete_field(id)
{
$("#"+id+"").remove();
}
function add_form_field()
{
id = Math.random();
html = '<table id='+id+'>\
<tr><td>Label </td></tr>\
</table>\
\
<button onclick=delete_field('+id+')>remove</button>';
$("form").append(html);
}
</script>
</head>
<body>
<form>
</form>
<button onclick=add_form_field()> Add a field </button>
</body>
</html>
Don't use Math.random, rather increment a number and create ID like: #tab_NN.
Add an ID to your Form Element id=myForm
Delegate click events to dynamically generated delete buttons using .on()
While removing the table that matched the button data-* attribute, delete the button too using .add( this ) (where this stays for the clicked button)
var id = 0;
function delete_field(event){
event.preventDefault();
$("#tab_"+ $(this).data("remove")).add(this).remove();
}
function add_form_field(){
id += 1;
var html = '<table id="tab_'+ id +'">'+
'<tr><td>Label</td></tr>'+
'</table>'+
'<button data-remove="'+id+'" class="remove">remove</button>';
$("#myForm").append(html);
}
$('#addField').on('click', add_form_field);
$('#myForm').on('click', '.remove', delete_field);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="myForm"></form>
<button id="addField"> Add a field </button>
The code above allows you to have changes in the future markup cause it targets a specific ID, but in case your DELETE buttons will always be exactly after table than you can do it without assigning ID's, by simply using .prev("table"):
http://jsbin.com/wuqati/1/edit
function delete_field(event){
event.preventDefault();
$(this).prev("table").add(this).remove();
}
function add_form_field(){
var html = '<table>'+
'<tr><td>Label</td></tr>'+
'</table>'+
'<button class="remove">remove</button>';
$("#myForm").append(html);
}
$('#addField').on('click', add_form_field);
$('#myForm').on('click', '.remove', delete_field);
Math.random() produces a floating point number less than 1 which is invalid for an id. You can use a global variable to keep count of the rows created. Keep in mind that a CSS ID can not start with a digit. So append the number to a string before using it as an ID.
<script>
function delete_field(id)
{
$("#"+id+"").remove();
}
tableID = 1;
function add_form_field()
{
id = 'table-'+tableID;
html = '<table id='+id+'>\
<tr><td>Label </td></tr>\
</table>\
\
<button onclick=delete_field('+id+')>remove</button>';
$("form").append(html);
tableID++;
}
</script>
Why not simplify this by doing something like below.
$(".remover").click(function() {
$(this).parent().remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
<input type="text" placeholder="input One"/> <input type="button" class="remover" value="remove" />
</td> </tr>
<tr>
<td>
<input type="text" placeholder="input Two"/> <input type="button" class="remover" value="remove" />
</td> </tr>
<tr>
<td>
<input type="text" placeholder="input Three"/> <input type="button" class="remover" value="remove" />
</td> </tr>
</table>

Categories