Dynamically populate user input corresponding json data with jquery - javascript

I have a json data that is like this,
[
{
"metalTypeId": 1,
"metalTypeName": "copper"
},
{
"metalTypeId": 3,
"metalTypeName": "steel"
}
]
My html is structured like this:
<table id="lineItemTable">
<tr class="row_to_clone">
<td>
<select>
<option>Select One Option</option>
<option>copper</option>
<option>steel</option>
</select>
</td>
<td>
<p></p>
</td>
</tr>
<tr class="row_to_clone">
<td>
<select>
<option>Select One Option</option>
<option>copper</option>
<option>steel</option>
</select>
</td>
<td>
<p></p>
</td>
</tr>
</table>
What I want to do is when the user select one of the options in the dropdown, I want to populate the corresponding json data to the p tag in my td. And my table contains two identical rows.
So for example, if user select copper for the first table row, and select steel for the second table row, the corresponding p will populate text "1" and "3" to the html page. If user do not select both rows, only the row that is selected will populate corresponding data to the p tag.
I am green to jQuery so I wrote some js code but it does not work as expected:
the variable that stores the json data is named as jasonData:
$('select').on('change', function (e){
$.each(jasonData, function(i, v) {
if (jasonData.metalTypeName == $('select').val()) {
$('p').text(v.metalTypeId);
return;
}
}); //end each()
}); // end on()
By looking at my code I already know one issue, the p and select select both two table row fields, but I do not know how to correctly fix it. The code may have other issues, please advice.

Your code is very close to working. You just need to cache the active select when it triggers the change event so you can reference it later; compare the active object in your each (you were incorrectly referencing the whole array); and use a few selectors to find the right paragraph. However, you may want to consider using something closer to David's answer. It's a bit cleaner than this method.
var jasonData = [
{
"metalTypeId": 1,
"metalTypeName": "copper"
},
{
"metalTypeId": 3,
"metalTypeName": "steel"
}
];
$('select').on('change', function (e){
var selected = this;
$.each(jasonData, function(i, v) {
if (v.metalTypeName === selected.value) {
$(selected).closest('.row_to_clone').find('p').text(v.metalTypeId);
return;
}
}); //end each()
}); // end on()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="lineItemTable">
<tr class="row_to_clone">
<td>
<select>
<option>Select One Option</option>
<option>copper</option>
<option>steel</option>
</select>
</td>
<td>
<p></p>
</td>
</tr>
<tr class="row_to_clone">
<td>
<select>
<option>Select One Option</option>
<option>copper</option>
<option>steel</option>
</select>
</td>
<td>
<p></p>
</td>
</tr>
</table>

I really recommend you not to use selectors so general such as "select" and "p"; while you are expanding your code, you'll get into issues because of these so generalized; I recommend you using some classes to help you or ID's.
Also, if you can change the structure of that JSON you won't need to do that each, basically you're forcing a O(n) problem there when you can something easier.
Here's an example I wrote for you doing the functionality that you want
http://jsfiddle.net/6v4zzgjj/
Now, if you want to make the selection of the results easier you can try the following
//Rename this variable better IE jsonData;
var jasonData = {"copper": { "metalTypeId": 1,"metalTypeName": "copper"}, "steel": {"metalTypeId": 3,"metalTypeName": "steel"}};
//Now the selector could be something like
$('.metalSelector').on('change', function (e){
var value = $(this).val();
$('#result').text(jasonData[value].metalTypeId);
});
That easy!

Related

How can i display data using Jquery append()

I've data
{product_name: "mushroom", id_p: 13, product_weight: "5", product_unit: "kg"}
How can I display product_weight after i select product name
<td class="col-md-7">
<select style="width:50%;" class="productcategory" id="prod_cat_id" name="id_c[]">
<option value="0" disabled="true" selected="true">category</option>
#foreach($category as $c)
<option value="{{$c->id_c}}" name="id_c" id="id_c">{{$c->category_name}}</option>
#endforeach
</select>
<select style="width:48%;" class="productname" name="id_p[]">
<option value="0" disabled="true" selected="true"> product</option>
</select>
</td>
<td class="col-md-1">
<div id="weights_wrapper" class="productweight" >
</div>
</td>
i want to output productweight in weight_warpper
for(var i=0;i<data.length;i++){
op+='<option value="'+data[i].id_p+'" name="id_p" data-product_weight="'+data[i].product_weight+'" data-product_unit="'+data[i].product_unit+'">'+data[i].product_name+'</option>';
}
$("select.productname").on("change",function(){
var weight = $(this).find(":selected").data("product_weight");
var unit = $(this).find(":selected").data("product_unit");
var span = "<span>"+weight+unit+"</span>";
$("#target_div_where_to_display_weight").html(span);
});
if I add new product my id weights_wrapper will change into weights_wrapper1 i want to output like not sure how to loop this
$("#target_div_where_to_display_weight '+ i +' ").html(span);
here is my append
$(document).ready(function() {
$('#add-form').click(function() {
i++;
$('#add-me').append(
+'<div id="weights_wrapper'+ i +'" class="productweight" name="product_weight">'
)};
I had an answer prepared based on the snips you put in the question, which was as simple as one change, but after looking at the full code, I see you are adding multiple whole rows of product selections, which each having their own weight display div.
A few things need to be changed, and tackled. The biggest problem you are facing is that you need to isolate your index used for each product row you are going to have on the page. Simply relying on the overused 'i' is causing you issues, since 'i' is not initially defined to cover the static html's elements, and its reused in for loops, and such. Gets confusing!
The first time the page is made (the first row, with the static html) should have an initial index set for the id's to use. Then when you add more whole rows, they continue the index value from there.
Static first row:
<tr>
<td class="col-md-7">
... snip ...
<select style="width:48%;" id="productname_1" id_index="1" class="productname" name="id_p[]">
<option value="0" disabled="true" selected="true"> product</option>
</select>
</td>
<td class="col-md-1">
<div id="weights_wrapper_1" class="productweight"></div>
</td>
</tr>
This would be considered row one, indexed to 1. Then when you add another whole row using the js, you need to first initialize that:
var id_i = 1;// 1 meaning one row already exists in the static html
Then follow with the other js output where you build another row, be sure to follow the same format as the initial static row (same id naming convention). Substituting "id_i" for the "1", so that it builds the html with "productname_2" and "weights_wrapper_2" etc.
$('#add-form').click(function() {
id_i++;// will change to '2' on first click
$('#add-me').append( ... the html build ... );
}
If you will spot further above in the "select" element, I added "id_index='#'", which can be used by jquery, to use the right index number to reference which one of the "weights_wrapper_#" you want to put the weight info span into:
$("select.productname").on("change",function(){
... snip ...
var id_index = $(this).attr("id_index");
$("#weights_wrapper_"+ id_index).html(span);
}

How to differentiate and club together multiple select dropdowns?

I have a table with multiple rows, and 4 columns. Each column contains a select dropdown, the options in the second column depends on the selection of first one, third one depends on second one and so on. I tried giving ids to selects and implementing onclick listeners. but it works only for the first row. Please help me solve this.
Here's the HTML code:`
<table>
{% for int i in (0,x) %}
<tr>
<td>
<select id='Product'>
<option>Car</option>
<option>Bike</option>
<option>Bus</option>
</td>
<td>
<select id='Model'>
</td>
<td>
<select id='Make'>
</td>
<td>
<select id='Color'>
</td>
</tr>
{% endfor%}
Here's the Jquery:
$("#product").change(function (event) {
event.preventDefault();
var val = $(this).val();
if( val == "none"){
$('#Model').empty().append($("<option></option>")
.attr("value","none")
.text("Select"));
$('#Make').empty().append($("<option></option>")
.attr("value","none")
.text("Select"));
$('#Color').val("Red");
}else{
var url_select = "/XYZ/product/?selected_product=" + val;
$(".innerload").css("visibility", "visible");
$.get(url_select, function(data){
$('#Model').empty().append($("<option></option>")
.attr("value","none")
.text("Select"));
$('#Make').empty().append($("<option></option>")
.attr("value","none")
.text("Select"));
$.each(data, function (i, item) {
$('#Model')
.append($("<option></option>")
.attr("value",item.model)
.text(item.model));
});
});
}
});
Similar jqueries for Model and Make onChange.
Please do not use same id in multiple time in loop id same for all time that's way it's not work

when option selected do stuff ( btw, all the elments have dynamic id)

I searched for similar questions, I found some but their solution did't help me.
For example:
First question
Second question
My problem is:
I have a table that the user can add rows dynamically, so I am creating a unique id for each row and all elements inside as well.
each row have two text fields and select with two options, and when you select one of the option the text feild should be dislpay:block and the second will be display: "none", depending on your choice.
I built here some example that will shows the general structure (JSFiddle)
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>
<input id="description-first-1" name="description-first-1" type="text" placeholder = "first">
<input id="description-second-1" name="description-second-2" type="text" placeholder = "second">
<select id="select-1">
<option>
<option id="first-opt-1">1</option>
<option id="second-opt-1">2</option>
</option>
</select>
</td>
</tr>
<tr>
<td>
<input id="description-first-2" name="description-first-1" type="text" placeholder = "first">
<input id="description-second-2" name="description-second-2" type="text" placeholder = "second">
<select id="select-2">
<option>
<option id="first-opt-2">1</option>
<option id="second-opt-2">2</option>
</option>
</select>
</td>
</tr>
$(function() {
$("#select-1").change(function() {
if ($("#first-opt-1").is(":selected")) {
$("#description-first-1").show();
$("#description-second-1").hide();
} else {
$("#description-first-1").hide();
$("#description-second-2").show();
}
}).trigger('change');
});
http://jsfiddle.net/8vz121rq/9/
In my example for that matter you can seen that there are only 2 rows but it can also be 10 rows with different id's.
How to get jquery identify which row and all the elements inside of it i'm changing if the id's of all elements is dynamic ?
First of all, you need event delegation as the rows are dynamically generated, such as:
$("table").on("change", "[id^='select']", function() {
// do your stuf
});
Or in your case:
$("table").on("change", "#select-1", function() {
// do your stuf
});
So, is this what you needed?
$(function() {
$("table").on("change", "[id^='select']", function() {
var $this = $(this);
var $row = $this.closest("tr");
var ID = this.id.replace(/^[^\-]+\-(\d+)$/gi, '$1');
var sIndex = $this.prop('selectedIndex');
var part = sIndex === 2 ? "second" : "first";
if (!sIndex) {
$row.find("input").show();
return;
}
$row.find("input").hide();
$row.find("#description-" + part + "-" + ID).show();
});
});
Demo#Fiddle
P.S. The above is purely based on your markup and ID structure!

Concise way to highlight label when items in dropdown changes?

I want to highlight labels with a color when the associated dropdown value changes.
<tr>
<td>
<select id="first_dd" data-bind="value: first">
<option>cat</option>
<option>dog</option>
<option>squirrel</option>
<option>birds</option>
</select>
</td>
<td>
<label id="first_lb">
soft</label>
</td>
</tr>
<tr>
<td>
<select id="second_dd" data-bind="value: second">
<option>lion</option>
<option>elephant</option>
<option>kangaroo</option>
<option>buffalo</option>
</select>
</td>
<td>
<label id="second_lb">
dangerous</label>
</td>
</tr>
I want to change the color of the first_lb when the first_dd items changed by the user.
How could I accomplish this in JavaScript/jQuery with less code?
Any suggestions highly appreciated.
So, here goes "less code".
Add change event handler to the select.
Try this:
$("#first_dd").change(function(){
$("#first_lb").css('color',"yellow");
});
DEMO
EDIT:
As your question asked only for first_dd and first_lb so I added code only for that part. To apply this to all selects use jquery .each().
If, you adding elements dynamically then you must use on to bind events, else it is enough to use .change().
So as you mentioned your requirements, do this:
$('select').each(function(){ //for each select elements in document
$(this).on('change',function(){ //bind change event
var id = $(this).attr('id').replace('dd','lb'); //get id for label
$("#"+id).css("color","yellow"); //highlight
})
})
DEMO
Make use of for attribute to connect labels with related select dom elements like
<select id="first_dd" data-bind="value: first">
<option>cat</option>
<option>dog</option>
<option>squirrel</option>
<option>birds</option>
</select>
<label for="first_dd">soft</label>
Add JS to detect Change and add class
$('select').each(function(){
$(this).on('change',function(){
$('label[for="'+$(this).attr('id')+'"]').addClass('changed')
})
})
And add appropriate CSS for changed class
.changed {
color: #000;
}

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