May I get help converting this piece of jQuery to vanilla JS?

Hi all.

I’ve got 2 select elements in html. The first select element has options A, B, C. Depending on the user’s selection, the second select element gets a unique set of options. These sets of options are brought in from php, which I’ve passed through to JSON like so:

var series = <?php echo json_encode($to_encode); ?>;
which produces an array of objects like this:

[ {supplier_id: "1", name: "Almonds", product_id: "1"}
, {supplier_id: "1", name: "Peanutes", product_id: "2"}
, {supplier_id: "1", name: "Pistachio", product_id: "3"}
, {supplier_id: "2", name: "Almonds", product_id: "4"}
, {supplier_id: "2", name: "Figs", product_id: "5"}
, {supplier_id: "2", name: "Walnuts", product_id: "6"}
]

This is my jQuery code: (works seamlessly! see fiddle: https://codepen.io/mslilafowler/pen/mdRegBz )

	$(".array_of_orders").change(function(){
		var array_of_orders = $(this).val();</option>';
		var options;
		$(series).each(function(index, value){
			if(value.supplier_id == array_of_orders){
				options += '<option value="'+value.product_id+'">'+value.name+'</option>';
			}
		});
		
		$('.array_of_products').html(options);
	});

I’ve always sucked at DOM and traversing. This is my best try, but it’s completely jumbled and producing undefined values:

document.querySelector(".array_of_orders").addEventListener("change", (e) => { 
		e = document.querySelector(".array_of_orders");
		var array_of_orders = e.value;
		var options;

		// var obj = JSON.parse(series);
		var obj = series;

	var sel = document.querySelector('.array_of_products');
	    
	    obj.forEach( function(user){
		    let opt = document.createElement('option');
		    opt.value=series.product_id;
		    opt.innerHTML += series.name
		    sel.appendChild(opt);
	   });
		console.log(array_of_orders);
	});

Any help would be great.

You define e as a parameter, but then you turn around in the next line and assign a different value to it. Since you are not going to use the value passed to the event listener, do not define.

The above line is not needed as you never reference it again.

Not sure what the purpose of this line is as you can just reference series in the forEach instead.

series is an array. How do you reference an element in an array?

You defined a parameter user for the forEach callback function, yet you do not use it. If you are not sure what user represents, I suggest reviewing the documentation for forEach.

I strongly suggest creating variable names that describe the data contained within them. It makes it easier for you (and others) to understand the intent of your code. Variables like e don’t explain the purpose of the data.

Another example is array_of_orders. I expect that variable to contain an array, but it will only contain a string. The same goes with ids and class names in your HTML. They should make sense as to the content contained within the elements for which they are applied.

I had the variables named properly etc but after hours of trying I guess I must have jumbled everything up. I tried again and cannot figure out how to get the exact code to work in JS :sleepy:

I would start over and try to get the variable names matched up. You can always post your updated code here and we can take a look.

You were close… mebbe something kinda like …

let series =
[ {supplier_id: "1", name: "Peanuts", product_id: "1"}
, {supplier_id: "1", name: "Almonds", product_id: "2"}
, {supplier_id: "1", name: "Pistachio", product_id: "3"}
, {supplier_id: "2", name: "Almonds", product_id: "4"}
, {supplier_id: "2", name: "Figs", product_id: "5"}
, {supplier_id: "2", name: "Walnuts", product_id: "6"}
];

const products = document.querySelector('.array_of_products');
const orders   = document.querySelector('.array_of_orders');

orders.addEventListener('change', (event) => {  
  products.innerHTML = "<option selected disabled>Select Product</option>";  
	let option_Id      = event.target.value;   
		series.forEach( function(elem, index){
			if(elem.supplier_id === option_Id){	       
        let opt   = document.createElement("option");
        opt.value = elem.product_id;
        opt.text  = elem.name;       
        products.add(opt, null);
			}
		});	
	});

After looking at your code a bit more, I wondered if in the end you might want the products to changed based on which order was selected. I assumed the the supplier_id referenced an order selected. With the following code, as the order selected changes, the products associated with that order (as related to supplier_id) change also.

var series = [
  { supplier_id: "1", name: "Peanuts", product_id: "1" },
  { supplier_id: "1", name: "Almonds", product_id: "2" },
  { supplier_id: "1", name: "Pistachio", product_id: "3" },
  { supplier_id: "2", name: "Almonds", product_id: "2" },
  { supplier_id: "2", name: "Figs", product_id: "5" },
  { supplier_id: "2", name: "Walnuts", product_id: "6" }
];

document.querySelector(".order-selector").addEventListener("change", function() {
  var productSelector = document.getElementById("product-selector");
  var selectedValue = this.value;
  var options = `<option selected disabled>Select Product</option>`;
  series.forEach(function (order) {
    if (order.supplier_id === selectedValue) {
      options += `<option value="${order.product_id}">${order.name}</option>`;
    }
  });
  productSelector.innerHTML = options;
});

This may not be your end goal, but the code does let you see one possible way of accomplishing such a task.

It would probably make more sense that when a different order is selected, all possible products are shown, but only the items specified for an order (based on supplier_id) are selected in the list. I could post code for this case if there is an interest.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.