Using JavaScript to add TR+TD Content using one selection input - javascript

I have one selection input with about 5 options in it. I also have one empty table that will use this format:
<table>
<tr>
<td>X(for delete)</td>
<td>Option name</td>
<td>Value that is linked to that option name</td>
</tr>
</table>
So what I want is this: when someone chooses a option from the select menu it has to make one new <tr> element in the table with 3 <td>. The first is just a "X" or image so that I can delete the <tr>, the second one is the option name and the third one a value that is linked to that option.
So how can I make a program that will add the TR for me and the TD's. The second part is: how can I make it so that when the user prewses the X it deletes the entire <tr> parent. And if possible how can I add all the values together from the 3 TD and display it on screen?
I know this is a lot but is there anyone here that can help me out?
Thanks for your time.

Try this, hope it helps you in the right way:
$('button').click(function() {
$('table').append('<tr><td class="remove">X</td><td class="optionValue">' + $('select option:selected').text() + '</td><td class="linkedValue">' + $('select').val() + '</td></tr>');
})
$(document).on('click', '.remove', function() {
$(this).parent().remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<button type="button">Enter</button>
<br />
<br/>
<table>
<tr>
<td>X(for delete)</td>
<td>Option name</td>
<td>Value that is linked to that option name</td>
</tr>
</table>

Related

JavaScript, append HTML and reference IDs in function

I have a form that shows a drop-down menu and a text field next to it:
<html>
<body>
<table>
<tbody class="project_wrapper">
<tr>
<td scope="row">
<select id="test_project" name="test_project[]">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input id="test_value" name="test_value[]" type="text" placeholder="Enter value"></td>
<td><div id="test_calc"></div></td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="3">
Add another project
</td>
</tr>
</tbody>
</table>
</body>
</html>
You can select one of the values in the drop-down, and when you enter a numeric value into the text field, on each keyup, it'll display the value multiplied by the selected value. You can also click the "Add another project" link and it'll append/create another drop-down and text field. This already works, and is done with the following Jquery code:
<script type="text/javascript">
$(document).ready(function(){
var addProject = $('.add_project');
var wrapper = $('.project_wrapper');
var projectHTML = `<tr>
<td scope="row">
<select id="test_project2" name="test_project[]" class="custom-select">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input id="test_value2" name="test_value[]" type="text" placeholder="Enter value"></td>
<td><div id="test_calc2"></div></td>
</tr>`;
$(addProject).click(function(){
$(wrapper).append(projectHTML);
});
});
$('#test_value').keyup(function(){
$('#test_calc').text(Math.round($(this).val() * $("#test_project option:selected").val()));
});
The problem is I can't get the multiplication function to work/display the result for any newly appended lines. Above you can see I tried hardcoding the values of test_value2 and test_calc2 and then added this below:
$('#test_value2').keyup(function(){
$('#test_calc2').text(Math.round($(this).val() * $("#test_project2 option:selected").val()));
});
I would expect the result (at least for one new appended line) to appear in the same way as for the first line, but nothing seems to happen. My goal is to get the results to appear for the appended line, and then also find a way to have that keyup calculation function work for any number of appended lines (rather than hardcode 2, 3, 4, etc. values).
The ids, I think, will need to be dynamically assigned as the lines are appended, and then the name will stay the same to hold the arrays for test_array and test_value which I'm going to receive and process via PHP.
Thanks!
Remove all your IDs from the template rows, use classes or name="" instead as your selectors
Assign an ID to your TBODY, we'll use it as the .on() event delegator
Use the "input" event, not the "keydown" event. You can also copy/paste values, remember?
on "input" - refer to the parent TR using .closest() before descending back (using .find()) to find the elements specific for that row
Use parseInt() or parseFloat() to handle input strings. Also remember to always fallback to a number i.e: 0 to prevent NaN results
jQuery(function($) {
const projectHTML = `<tr>
<td>
<select name="test_project[]" class="custom-select">
<option value="" selected>Select</option>
<option value="10">10</option>
<option value="20">20</option>
</select>
</td>
<td><input name="test_value[]" type="type" placeholder="Enter value"></td>
<td><div class="result"></div></td>
</tr>`;
const $projects = $("#projects"); // assign an ID to your tbody
const $addProject = $('.add_project');
const arrRow = () => $projects.append(projectHTML);
// Create new row on click
$addProject.on("click", arrRow);
// Add the first row
arrRow();
// use a delegator which is not dymanic (the TBODY in this case),
// and use delegated events to any ":input" element:
$projects.on("input", ":input", function(ev) {
const $tr = $(this).closest("tr");
const $project = $tr.find('[name="test_project[]"]');
const $value = $tr.find('[name="test_value[]"]');
const $result = $tr.find(".result");
const project = parseInt($project.val(), 10) || 0;
const value = parseFloat($value.val()) || 0;
const result = project * value;
$result.text(result);
});
});
<table>
<tbody id="projects"></tbody>
<tbody>
<tr>
<td colspan="3">
Add another project
</td>
</tr>
</tbody>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
The IDs must be unique, instead whenever you add another row you duplicate the IDs.
Instead of IDs I changed them to class in order to combine this keyword with .closest() and .find() to get the values of interest.
Moreover, because you add new elements to the table you need to delegate the event.
If you change the select you need to calculate again, not only on typing into the input field.
var addProject = $('.add_project');
var wrapper = $('.project_wrapper');
var projectHTML = '<tr>\
<td scope="row">\
<select class="test_project" name="test_project[]" class="custom-select">\
<option selected>Select</option>\
<option>10</option>\
<option>20</option>\
</select>\
</td>\
<td><input class="test_value" name="test_value[]" type="number" placeholder="Enter value"></td>\
<td><div class="test_calc"></div></td>\
</tr>';
$(addProject).click(function () {
$(wrapper).append(projectHTML);
});
$(document).on('input', '.test_value', function (e) {
$(this).closest('tr').find('.test_calc').text(Math.round($(this).val() * $(this).closest('tr').find('.test_project option:selected').val() || 0));
});
$(document).on('change', '.test_project', function(e) {
$(this).closest('tr').find('.test_value').trigger('input');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody class="project_wrapper">
<tr>
<td scope="row">
<select class="test_project" name="test_project[]">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input class="test_value" name="test_value[]" type="number" placeholder="Enter value"></td>
<td>
<div class="test_calc"></div>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="3">
Add another project
</td>
</tr>
</tbody>
</table>

Setting default value in dropdown after changing element jQuery

I apologize in advance if this question/issue was brought up or asked. I did not find one of this type.
On button click, I would like to change the data field into a dropdown list that defaults to the value that was present before the change.
$("#edit").on("click", function() {
let food = $("#food");
let foodValue = food.attr("data-food-value");
food.html(`<select>
<option value="1">Fries</option>
<option value="2">Burger</option>
<option value="3">Pizza</option>
</select>`);
$(`#food select option[value="${foodValue}"]`).attr("selected", true);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<th>Favorite Food</th>
<td id="food" data-food-value="3">Pizza</td>
</tr>
<tbody>
</table>
<button id="edit">Edit</button>
I want it to default to Pizza on button click, but it defaults to Fries. Any help is greatly appreciated. Thank you in advance.

Trouble cloning a set of selects dependent on each other

I am trying to create a dynamic table that allows the user to select from around 100 variables. These variables have been split into categories and I have been displaying them in a second select that depends on the user selecting a value in the first select. I have been searching the web for answers and have come up blank. I realize that the clone() call will duplicate all data and for that reason id's are a poor choice for the rows.
Here is what I currently have for HTML:
<body>
<table name='myTable' class="dynatable">
<thead>
<tr>
<th class='idCol' >ID</th>
<th>Category</th>
<th>Metric</th>
<th>Conditional</th>
<th><button class="add">Add</button></th>
</tr>
</thead>
<tbody>
<form name='myForm'>
<tr class="first">
<td class="id idCol"><input type="text" name="id[]" value="0" /></td>
<td><select name='categories' onChange='updatemetrics(this.selectedIndex)' style="width: 260px">
<option selected>--Select Category--</option>
<option value='1'>Customer Experience</option>
<option value='2'>Key Satisfaction Identifiers</option>
<option value='3'>Personnel Costs</option>
<!-- I have cut the rest out for the sake of brevity. -->
</select></td>
<!-- This is the select that populates based on the user's choice. -->
<td><select style="width: 310px"name='metrics'></select></td>
</tr>
</form>
</tbody>
</table>
</body>
The Javascript that I am working with is as follows.
$(document).ready(function() {
var id = 0;
// Add button functionality
$("table.dynatable button.add").click(function() {
id++;
var master = $(this).parents("table.dynatable");
// Get a new row based on the prototype row
var prot = master.find(".prototype").clone(true);
prot.attr("class", "")
prot.find(".id").attr("value", id);
master.find("tbody").append(prot);
});
// Remove button functionality
$("table.dynatable button.remove").live("click", function() {
$(this).parents("tr").remove();
});
});
//script for dynamically populating the metrics select
var metricCategories=document.myForm.categories;
var metricList=document.myForm.metrics;
var metrics=new Array()
metrics[0]=" "
metrics[1]=['Wait time average|waitInLine','Mystery Shopper Scores|mysteryScores']
metrics[2]=['Referral Rate|ref_rate','Facebook Shares|facebook_shares','Twitter Followers|twit_followers','Customer Complaint Calls|comp_calls']
metrics[3]=['Pension Payouts|pension_pay', 'Full Time Employees|ftes', 'Part Time Employees|ptes', 'Contractor Costs|contract_costs']
function updatemetrics(selectedMetricGroup){
metricList.options.length=0
if (selectedMetricGroup>0) {
for (i=0; i<metrics[selectedMetricGroup].length; i++)
metricList.options[metricList.options.length]=new Option(metrics[selectedMetricGroup][i].split("|")[0], metrics[selectedMetricGroup][i].split("|")[i])
}
}
Any help would be appreciated. To reiterate the reason I am asking for help, I need to add/ remove rows that hold select nodes that interact with each other. Thanks in advance.

appendTo - next to instead of below

<table id="tab" border="2">
<tbody>
<tr> <td>aaa</td><td>aaa</td></tr>
<tr> <td>bbb</td><td>bbb</td></tr>
<tr id="www"> <td><select id="sel">
<option value="one">One</option>
<option value="two">Two</option>
<option value="three">Three</option>
</select> </td><td>ccc</td></tr>
<tr> <td>xxx</td><td>xxx</td></tr>
<tr> <td>yyy</td><td>yyy</td></tr>
<tr> <td>zzz</td><td>zzzz</td></tr>
</tbody>
</table>
$("#sel").change(function(){
if( $(this).val() === 'three' )
$('<tr class="new"><td>new</td><td>new</td></tr>').appendTo('#www');
else
$('#tab tr.new').remove();
});
LIVE: http://jsfiddle.net/jSMBZ/7/
why this add new column next to #www instead of below? how can i fix it?
The two rows are being appended inside the #www td instead of after it. To add it after, you need to use the .after(content) jQuery Function like so:
$("#sel").change(function(){
if( $(this).val() === 'three' )
$('#www').after('<tr class="new"><td>new</td><td>new</td></tr>');
else
$('#tab tr.new').remove();
});
Here is the jsFiddle Link with the updated example which works as you have described: http://jsfiddle.net/jSMBZ/12/
I think rather than using appendTo you will want to use insertAfter. That way it should be inserted after the tag is closed instead of being appended to it before it's closed.
Use
$('#www').after('<tr class="new"><td>new</td><td>new</td></tr>');
Rather than append, use after (docs):
$('#www').after('<tr class="new"><td>new</td><td>new</td></tr>');
http://jsfiddle.net/9vKH4/

Get all selects after a current select element in a row

Let's say I have a table like this with multiple selects in very row:
<table>
<tr>
<td>
<select name="selectA" id="selectA">
....
</select>
</td>
<td>
<select name="selectB" id="selectB">
....
</select>
</td>
<td>
<select name="selectC" id="selectC">
....
</select>
</td>
</tr>
<tr>
<td>
<select name="selectA2" id="selectA2">
....
</select>
</td>
<td>
<select name="selectB2" id="selectB2">
....
</select>
</td>
<td>
<select name="selectC2" id="selectC2">
....
</select>
</td>
</tr>
<tr>
<td>
<select name="selectA3" id="selectA3">
....
</select>
</td>
<td>
<select name="selectB3" id="selectB3">
....
</select>
</td>
<td>
<select name="selectC3" id="selectC3">
....
</select>
</td>
</tr>
</table>
What I want to do is, when a select element changes, I want to get all select elements in the same row after the changed select element and change something with them as well.
So if selectA changes, I want to get selectB and selectC. If selectB changes, I want to get selectC. And so on. How to do that with jQuery?
Try this:
$('select').change(function() {
$(this).parent().nextAll().find('select')...
});
i.e. take the element's .parent() (which will be the <td>), then for all of its following siblings .nextAll(), .find() all <select> elements within them.
There are many jquery plugins that facilitate creating cascading dropdowns, which, in a nutshell, is what you want to achieve.
Here's a google search on "cascading dropdown jquery"; pretty much every result is a jQuery plugin :)
A slight modification of the Alnitak solution would be to bind the event handler on table level instead, so that you end up with only one function bound doing the job:
$('table').change(function(event) {
$(event.target).parent().nextAll().find('select')...
event.stopPropagation();
});
This will get you all the selects that are in the same row:
$("table select").change(function(){
var $select_mates=$('select', $(this).closest('tr'));
});
If you don't want the element itself:
$("table select").change(function(){
var $me=$(this);
var $select_mates=$('select', $me.closest('tr')).not($me);
});
My solution uses the jQuery Selector Context.
EDIT: Now I recognized I haven't seen after a current select element :). Let's see:
$("table select").change(function(){
var $me=$(this);
var $select_mates=$('select', $me.closest('tr'));
var $select_after_mates=$select_mates.slice($select_mates.index($me)+1);
});
Ok, this works, I've finally figured out how to do this:
$("table select").change(function(){
$(this).parent().nextUntil().find("select option:first").attr("selected", "selected");
});
i would try something like
//"obj" being your <select> HTML element
jQuery(obj).parent().find("select").not(obj);
UPDATE
I know the answer is already there but i thought for completeness I'd add a fix:
//"obj" being your <select> HTML element
// .parent().parent() gets the row
// .find("select" finds all the selects contained somewhere in that row.
// .not(obj) removes your current <select>
jQuery(obj).parent().parent().find("select").not(obj);

Categories

Resources