0

I am sure this has been done and I suspect I am just not searching for the correct terms so please don't blast me for asking something that has already been answered.

I have an array of item attributes (dynamic) and I want to drill down with select boxes to a final item.

var JSONarray = [
 {'itemAtID':1, 
  'attribute1':'sm',
  'attribute2':'blue',
  'attribute3':'short sleeved'
 },
 {'itemAtID':2, 
  'attribute1':'med',
  'attribute2':'blue',
  'attribute3':'short sleeved'
 },
 {'itemAtID':3,
  'attribute1':'lg',
  'attribute2':'white',
  'attribute3':'short sleeved'
 },
 {'itemAtID':4, 
  'attribute1':'med',
  'attribute2':'white',
  'attribute3':'short sleeved'
 },
 {'itemAtID':5,
  'attribute1':'lg',
  'attribute2':'blue',
  'attribute3':'long sleeved'
 }];

UPDATED ARRAYS

var JSONarray = [
 {'itemAtID':1, 
  'attribute1':'sm',
  'attribute2':'blue',
  'attribute3':'short sleeved',
  'QoH': 3,
  'image': '101001506-1.jpg'
 },
 {'itemAtID':2, 
  'attribute1':'med',
  'attribute2':'blue',
  'attribute3':'short sleeved',
  'QoH': 3,
  'image': '101001506-2.jpg'
 },
 {'itemAtID':3,
  'attribute1':'lg',
  'attribute2':'white',
  'attribute3':'short sleeved',
  'QoH': 3,
  'image': '101001506-3.jpg'
 },
 {'itemAtID':4, 
  'attribute1':'med',
  'attribute2':'white',
  'attribute3':'short sleeved',
  'QoH': 3,
  'image': '101001506-4.jpg'
 },
 {'itemAtID':5,
  'attribute1':'lg',
  'attribute2':'blue',
  'attribute3':'long sleeved',
  'QoH': 3,
  'image': '101001506-5.jpg'
 }];


var formFields =  [
  {'name':'itemAt1',
   'label': 'Size',
   'fieldOpts': ['sm','med','lg','xl']
  },
  {'name':'itemAt2',
   'label': 'Color',
   'fieldOpts': ['blue','white','black']
  },
  {'name':'itemAt3',
   'label': 'Style',
   'fieldOpts': ['short sleeve','long sleeve']
  }
 ];

I have three dynamically generated select boxes:

UPDATED TO REFLECT INITIAL OPTIONS IN ALL SELECT BOXES

 <form>
  <label>Size</label>
  <select name="attribute1" id="id_attribute1">
   <option value="">Select Size</option>
   <option value="sm">sm</option>
   <option value="md">md</option>
   <option value="lg">lg</option>
  </select>

  <label>Color</label>
  <select name="attribute2" id="id_attribute2">
   <option value="">Select Color</option>
   <option value="blue">blue</option>
   <option value="white">white</option>
  </select>

  <label>Style</label> 
  <select name="attribute3" id="id_attribute3">
   <option value="">Select Style</option>
   <option value="short sleeve">short sleeve</option>
   <option value="long sleeve">long sleeve</option>
  </select> 
 </form>

When a user selects the size, I want to query the array and return the available colors. When the user selects style, I want to return the itemAtID.

This is a very simplified representation of what I am trying to accomplish, but if I can make this work, I can scale it up to suit my purpose. I am sure there has to be a plugin for this but I have not been able to find one that doesn't require AJAX which puts an unnecessary load on the server as the data has already been passed in the original array of objects.

UPDATE I have realize that I need to refine my original plan a little to make it more useable. The user should be able to select any of the select boxes first and the options for the remaining unselected boxes should be updated as enabled or disabled based on either their existence or the QoH (quantity on hand). Options that don't exist in the JSONarray (like the black color) should not appear, but options that exist but not in the selected size/color/style or with a 0 QoH should be disabled.

When selections for all boxes have been made, the JSONarray should be queried for the itemAtID matching those options and a hidden field (itemAtID) should be updated and the submit button should be enabled.

So my plan is to use a class based onChange to trigger the function.

Create empty array (formSelects).

Loop through the formFields array and 1)enable or disable options based on the the current field selection and 2)when a selection exists, push it to the formSelects array.

If the formSelects.length equals the formFields.length, search the JSONarray for the row that matches the criteria and update the hidden itemAtID field and enable the submit button (and eventually update the image).

I think that will address my problems. If anyone sees any flaws in this plan, please let me know. I am not very fluent in jQuery so it would be nice to find out my plan won't work before I spend the next day trying to sort out the proper syntax.

UPDATE: just realize the first flaw. I have to figure out a way to deal with resetting the form so you don't get pigeon holed by your selections...in other words, if you style selection disables a size or color you would rather have, you would be stuck...not sure how to handle that.

Thanks for your help and your patience with my shifting plan.

2
  • I have realized my initial plan for this function was flawed in that it didn't handle three or more cascading selects well (ended up with duplicate options in all but the first and last selects. It also limited the user to having to select options in a specific order which isn't ideal. So I am working on an updated set of data to work with...an array of select boxes with arrays of available options. Instead of filtering the options as selections are made, I want to disable options. I also want to be able to select from any box first, updating the remaining selects. Commented Dec 10, 2017 at 20:10
  • The new implementation will have to determine when all of the options have been selected and then filter the original array of attributes for one that meets all of those criteria and then update a hidden field (itemAtID) with that selection. I am also adding a QoH (quantity on hand) field to the array (used to determine whether an option should be enabled or disabled) and an image field to update the product image when the final selection is made. Commented Dec 10, 2017 at 20:20

2 Answers 2

1

You can use this code,

//Populate Colors based on Size Selected    
$('#id_attribute1').on('change',function(){
$("#id_attribute2").empty();
$("#id_attribute2").append('<option value="">please select color</option>');
for(var i = 0 ; i < JSONarray.length ; i++)
   {
      if(JSONarray[i]['attribute1'] == this.value)
         {
             $("#id_attribute2").append('<option value="'+JSONarray[i]['attribute2']+'">'+JSONarray[i]['attribute2']+'</option>');
         }
    }
});

//Populate Style based on Color Selected
$('#id_attribute2').on('change',function(){
$("#id_attribute3").empty();
$("#id_attribute3").append('<option value="">please select style</option>');
for(var i = 0 ; i < JSONarray.length ; i++)
   {
       if(JSONarray[i]['attribute2'] == this.value)
          {
              $("#id_attribute3").append('<option value="'+JSONarray[i]['itemAtID']+'">'+JSONarray[i]['attribute3']+'</option>');
          }
   }
});

//Return ItemAtID base on Style selected
$('#id_attribute3').on('change',function(){
    alert(this.value);
});

Above is the straight forward way. You can reduce the code as follows,

//All Change event handled by single function
$('#id_attribute1,#id_attribute2,#id_attribute3').on('change',function(){
var id = this.id.substr("id_attribute".length); // id will give 1 or 2 or 3 that can be used to identify the select boxes
//id = 3 for the #id_attribute3 
if(id == 3)
{
    alert(this.value);
}
else
{
    var newid = parseInt(id) + 1;
    //Find the select box to populate
    var $newattrid = $("#id_attribute"+ newid);
    var attribute = 'attribute'+ newid;
    $newattrid.empty();
    //id = 1 for the #id_attribute1 
    if(id == 1)
    {
        $newattrid.append('<option value="" class="select">please select color</option>');
    }
    //For the #id_attribute2 
    else
    {
        $newattrid.append('<option value="">please select style</option>');
    }

    for(var i = 0 ; i < JSONarray.length ; i++)
    {
         if(JSONarray[i]['attribute'+id] == this.value)
         {
             if(id == 1)
             {
                  $newattrid.append('<option value="'+JSONarray[i][attribute]+'">'+JSONarray[i][attribute]+'</option>');
             }
             else
             {
                  $newattrid.append('<option value="'+JSONarray[i]['itemAtID']+'">'+JSONarray[i][attribute]+'</option>');
             }
          }      
     }
}
});
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the response. I think this looks like the best option so far. I have been researching using grep to filter down the results but this looks pretty straight forward. I will let you know what happens.
@JasonPeterman see the updated answer. Check the reduced code format.
I implemented your first solution and it worked well. But as made changes to it to meet the requirements of the actual implementation, I realized there were some problems...not with your code, but with my original plan. When you add a third option, you end up with duplicate options in the second select. Also, I ran into issues if you select an option from the second select before the first. So I am currently working on an solution that loops through an array of selects, and enables or disables options based on the current selections. I will post once I make a little more progress.
And in order to make this work, I realized that instead of changing the value of the last select to the itemAtID, I need to determine if all of the select boxes have selected options and at that point, filter the original options array for a row that meets all selections and then update a hidden field with the itemAtID.
0

For the id_attribute2 id select values you could do.

$(document).on('change','#id_attribute1',function(){
     let tmpVal = $(this).find("option:selected").val();
     $("#id_attribute2").html('<option value="">please select color</option>');
     for(var z = 0 ; z < JSONarray.length ; z++)
     {
        if(JSONarray[z]['attribute1'] == tmpVal)
           $("#id_attribute2").append('<option value="'+JSONarray[z]['attribute2']+'">'+JSONarray[z]['attribute2']+'</option>');
     }
});

2 Comments

I couldn't understand from the question which array item is to be displayed on the change of the second select box. Although the code will be exactly same, just need to change some fields.
Thanks for the response. What make this challenging is everything is dynamic. There may be one select box...there may be 3. The labels are dynamic as are all of the options for each. Most of the functionality is handled on the back end and what I do is produce a structurally consistent JSON array. So the first select box will use the values from attribute 1, second(if needed) from attribute 2 an so on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.