Solved

jquery add table row with json data in dropdowns

Posted on 2011-03-07
9
1,326 Views
Last Modified: 2013-11-11
Hi, I have a web form with a table that the user can add additional rows to. The first row of the table consists of dependent dropdowns. The dropdowns are populated with json data from a referenced file. The code that I am using for it is as follows:

   
 $("#section").change( function () {
    var sSec =$(this).val();
    
    $("#divParts").hide();
    $("#divDesc").hide(); 
    $("#divGroup").hide(); 
    if(sSec=="select") {
    $("#divCategory").hide();
    } else {
    $.getJSON("static/site_category.json",  function(json) {
    var catJson = json[sSec];
    var options = "<option value=\"select\">Select Area Type</option>";
    for(i=0;i<catJson.length;i++) {
    options +="<option value=\""+catJson[i].ky+"\">"+catJson[i].val+"</option>"
    }
    
    $("#category").html(options);
    $("#divCategory").show();    
    });
    }
    }); 

Open in new window


This is only one dropdown, but it illustrates that I am trying to hide/show other dropdowns based on user selection.

For the add row function, I use this code:

     
 var currentItem = 1; 
     $("#addRow").live("click", function() {
    	  
    	   currentItem++; 
    	   var currentItem = 1; 
          //clone last row to variable
       var row = $('#details tbody>tr:last').clone(true);
          //clear text boxes
        $("td input:text", row).val("");
        //clear selection boxes
         $("select option:selected", row).attr("selected", false);
          //clear empty cells
    
          //add row
     row.insertAfter('#details tbody>tr:last');
        return false;
     }); 

Open in new window


To make this bit of code work, I have created a hidden field that acts as a counter. When the user clicks on the add row button, the counter increases and theoretically, a new row is added and the first section of code I pasted will work for each additional row. However, the results are not like that at all. Instead, when the row is added and the user makes a selection on the new row, the values are updated in the first row. I then tried to add a dynamic ID to the dropdown selection ID each time that the add row button is clicked so that the ID would match the hidden counter field, but the results were not correct either. In this scenario, the values of each added row were changed when the first row dropdown values were changed.

I appreciate any help to get this code working as desired - which would be a simple added row where the dropdown selections only update on the row that they are found on. Thank you.
0
Comment
Question by:wbpw
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
9 Comments
 
LVL 82

Expert Comment

by:leakim971
ID: 35060029
Could you post a row or better the main HTML code ?
0
 

Author Comment

by:wbpw
ID: 35060153
Yes, here is the row to be duplicated:
<tr class="rec-rows"> 
<td width="" align="left">
<div><select id="section" name="section" style="margin-top:15px;">
<option value="select">Select Area</option>
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
</select>
</div>
</td> 
<td width="" align="left">
<div id="divCategory" style="display:none;margin-top:15px;">
<select id="category" name="category"></select>
</div>
</td> 
<td width="" align="left">
<div id="divGroup" style="display:none;margin-top:15px;">
<select id="group" name="group"></select>
</div>
</td> 
<td width="" align="left">
<div id="divParts" style="display:none;margin-top:15px;">
<select id="parts" name="parts"></select>
</div>
</td> 
<td width="" align="left">
<div id="divDesc" style="display:none; margin-top:15px;">
<select id="desc" name="desc"></select>
</div>
<div id="divText" style="display:none">
Type Description:
<input type="text" value="" id="text" name="text" style="width: 100px;" />
</div>
</td> 
<td width="" align="left">Qty:<input type="text" name="quantity" style="width:30px" id="quantity"/></td> 

</tr> 

Open in new window

0
 
LVL 82

Accepted Solution

by:
leakim971 earned 500 total points
ID: 35060515
First as you know << id >> must be unique in a document. You should (MUST) not have the same id for more than one element.
You may use the row as context to select the right element. For example to clear all input in the current row (this) : $("input", $(this).parens("tr")).val("");

Check this (I use class instead id) :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script language="javascript" src="http://code.jquery.com/jquery-1.5.min.js"></script>
<script language="javascript">
	$(document).ready(function() {
		$(".section").change( function () {
			context = $(this).parents("tr");
			var sSec = $(this).val();
			$(".divParts", context).hide();
			$(".divDesc", context).hide(); 
			$(".divGroup", context).hide(); 
			if(sSec=="select") {
				$(".divCategory", context).hide();
			}
			else {
				$.getJSON("static/site_category.json", function(json) {
					var catJson = json[sSec];
					var options = "<option value=\"select\">Select Area Type</option>";
					for(i=0;i<catJson.length;i++) {
						options += "<option value=\""+catJson[i].ky+"\">"+catJson[i].val+"</option>";
					}
					$(".category", context).html(options);
					$(".divCategory", context).show();
				});
			}
		});
	
		$("#addRow").live("click", function() {
			var row = $('#details tbody>tr:last').clone(true);
			$("td input:text", row).val("");
			$("select option:selected", row).attr("selected", false);
			$("#details").append(row);
		});
	
	});
</script>
</head>
<body>
<input type="button" value="Add row" id="addRow" />
<br />
<table id="details">
<tr class="rec-rows"> 
<td width="" align="left">
<div><select class="section" name="section" style="margin-top:15px;">
<option value="select">Select Area</option>
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
</select>
</div>
</td> 
<td width="" align="left">
<div class="divCategory" style="display:none;margin-top:15px;">
<select class="category" name="category"></select>
</div>
</td> 
<td width="" align="left">
<div class="divGroup" style="display:none;margin-top:15px;">
<select class="group" name="group"></select>
</div>
</td> 
<td width="" align="left">
<div class="divParts" style="display:none;margin-top:15px;">
<select class="parts" name="parts"></select>
</div>
</td> 
<td width="" align="left">
<div class="divDesc" style="display:none; margin-top:15px;">
<select class="desc" name="desc"></select>
</div>
<div class="divText" style="display:none">
Type Description:
<input type="text" value="" class="text" name="text" style="width: 100px;" />
</div>
</td> 
<td width="" align="left">Qty:<input type="text" name="quantity" style="width:30px" class="quantity"/></td> 
</tr> 
</table>
</body>
</html>

Open in new window

0
The Ultimate Checklist to Optimize Your Website

Websites are getting bigger and complicated by the day. Video, images, custom fonts are all great for showcasing your product/service. But the price to pay in terms of reduced page load times and ultimately, decreased sales, can lead to some difficult decisions about what to cut.

 

Author Comment

by:wbpw
ID: 35061109
Thank you leakim! Your solution solved two of my problems: 1) the clearing of values for each added row and 2) when a row is added, that specific row's content is updated.

However, I still have one other issue. The code you have provided does in fact leave the first dropdown visible. However, The onChange function is still .class specific. That is, when a new row is added and the user selects an option from any of the added rows, then all of the .classes that hide/show re-populate with the last selected values. How am I able to give a unique value to the first line in the code below so that when a user is finished selecting values from a row, they do not hide/show when they are selecting values from another row?

            
$(".section").change( function () { /// this needs to be unique
			context = $(this).parents("tr");
			var sSec = $(this).val();
			$(".divParts", context).hide();
			$(".divDesc", context).hide(); 
			$(".divGroup", context).hide(); 
			if(sSec=="select") {
				$(".divCategory", context).hide();
			}
			else {
				$.getJSON("static/site_category.json", function(json) {
					var catJson = json[sSec];
					var options = "<option value=\"select\">Select Area Type</option>";
					for(i=0;i<catJson.length;i++) {
						options += "<option value=\""+catJson[i].ky+"\">"+catJson[i].val+"</option>";
					}
					$(".category", context).html(options);
					$(".divCategory", context).show();
				});
			}
		});

Open in new window

0
 
LVL 82

Expert Comment

by:leakim971
ID: 35061404
>However, The onChange function is still .class specific. That is, when a new row is added and the user selects an option from any of the added rows, then all of the .classes that hide/show re-populate with the last selected values.
>$(".section").change( function () { /// this needs to be unique

Wrong, we check change event for all element having section as class but only one (with it's own context) is fired. That's why we're able to use $(this)
If we want to be sure, check length of selected element with for example : alert( $(".divParts", context).length )
0
 
LVL 82

Expert Comment

by:leakim971
ID: 35061522
Maybe I don't unserstood something (like usual :))
leakim971-417243.flv
0
 

Author Comment

by:wbpw
ID: 35072808
leakim, thank you for the visual. I just spent time trying to duplicate your results. I did get what you did! However, I also found where my error is. It seems I am getting the results I am getting when I place that table into the rest of the form, which is within another table. Below is the code the causes the results I was getting:

<form id="form" name="form">
<table width="100%" border="1" cellpadding="5" cellspacing="5" id="table1">
<tbody> 
<tr>
<td align="center" valign="top">
<input type="button" value="Add" id="addRec" style="width:150px;">
<input type="button" value="Delete" style="width:150px;">
</td>
<td valign="top">
<TABLE id="survey" style="margin-top:100px;">
<TR>
<TD colspan="2"> Name: </TD>
<TD colspan="2"><span class="requiredField">
<textarea name="area[]" cols="65" id="area[]"></textarea>
</span></TD>
</TR>
<TR>
</TR>
<TR>
<TD colspan="4" bgcolor="#0066FF">&nbsp;</TD>
</TR>
<TR>
<TD colspan="4">
<table width="100%" border="0" cellspacing="0" cellpadding="0" >        
<tr>
</table>
<table width="100%" border="0" cellspacing="0" cellpadding="0" id="details">
<tr><td><input name="addRow" type="button" class="add" value="+" id="addRow"></td></tr>
<tr class="rec-rows"> 
<td width="" align="left">
<div><select class="section" name="section" style="margin-top:15px;">
<option value="select">Select Area</option>
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
</select>
</div>
</td> 
<td width="" align="left">
<div class="divCategory" style="display:none;margin-top:15px;">
<select class="category" name="category"></select>
</div>
</td> 
<td width="" align="left">
<div class="divGroup" style="display:none;margin-top:15px;">
<select class="group" name="group"></select>
</div>
</td> 
<td width="" align="left">
<div class="divParts" style="display:none;margin-top:15px;">
<select class="parts" name="parts"></select>
</div>
</td> 
<td width="" align="left">
<div class="divDesc" style="display:none; margin-top:15px;">
<select class="desc" name="desc"></select>
</div>
<div class="divText" style="display:none">
Type Description:
<input type="text" value="" class="text" name="text" style="width: 100px;" />
</div>
</td> 
<td width="" align="left">Qty:<input type="text" name="quantity" style="width:30px" class="quantity"/></td> 
</tr> 
</table>
</TD>
</TR>
</TABLE>
</td>
</tr>
</tbody> 
</table>
</form>

Open in new window


Try this with your code and then you will see what I was getting. This leads me to think that this issue can be resolved by further declaring the context variable? Perhaps something like

context = $(this).parents("table:tr tr");

Open in new window


I am not sure. Let me know if you see what I mean about the results I was getting. Thanks!
0
 

Author Comment

by:wbpw
ID: 35072970
What I posted above is not close to what I need to do. However, it is official that the code doesn't work correctly when the table is nested within another table. Do you know how I would fix this? I am also still looking for a solution, will let you know if I find one.
0
 
LVL 82

Expert Comment

by:leakim971
ID: 35073267
Thanks for your feedback. Use :
$(this).parents("tr").filter(":first")

Open in new window

instead
$(this).parents("tr")

Open in new window

0

Featured Post

Transaction Monitoring Vs. Real User Monitoring

Synthetic Transaction Monitoring Vs. Real User Monitoring: When To Use Each Approach? In this article, we will discuss two major monitoring approaches: Synthetic Transaction and Real User Monitoring.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
This article demonstrates how to create a simple responsive confirmation dialog with Ok and Cancel buttons using HTML, CSS, jQuery and Promises
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question