Using javascript and jquery, to populate related select boxes with array structure

后端 未结 4 1184
日久生厌
日久生厌 2020-11-28 03:55

Using answers to this question, I have been able to populate a select box based on the selection of another select box. ( I posted my answer here) Pulling the data from an a

相关标签:
4条回答
  • 2020-11-28 04:17

    I really liked the solution by @Marko Dunic, but it didn't meet my needs for attaching IDs to the options. Once I attached the IDs, I realized that I could make the JS code even smaller and simpler. My solution is designed for when the data comes from a relational database, and the JSON input data retains the relational structure with Primary/Foreign Keys. Here is the JSON data:

    <html lang="en">
      <head>
        <title>Populate a select dropdown list with jQuery - WebDev Ingredients</title>
        <script type="text/javascript" src="js/jquery-1.4.2.js"></script>
        <script type="text/javascript">
            var types = [ 
                { typeID: 1, name: 'Domestic'},
                { typeID: 2, name: 'Import'},
                { typeID: 3, name: 'Boat'}
            ]
            var makes = [ 
                { typeID: 1, makeID: 1, name: 'Chevy'}, 
                { typeID: 1, makeID: 2, name: 'Ford'}, 
                { typeID: 1, makeID: 3, name: 'Delorean'}, 
                { typeID: 2, makeID: 4, name: 'Honda'}, 
                { typeID: 2, makeID: 5, name: 'Toyota'}, 
                { typeID: 2, makeID: 6, name: 'Saab'} 
            ]       
            var model = [ 
                { makeID: 1,  modelID: 1, name: 'Camaro'}, 
                { makeID: 1,  modelID: 2, name: 'Chevelle'}, 
                { makeID: 1,  modelID: 3, name: 'Nova'}, 
                { makeID: 2,  modelID: 4, name: 'Focus'}, 
                { makeID: 2,  modelID: 5, name: 'Galaxie'}, 
                { makeID: 2,  modelID: 6, name: 'Mustang'}, 
                { makeID: 4,  modelID: 7, name: 'Accord'},
                { makeID: 4,  modelID: 8, name: 'Civic'}, 
                { makeID: 4,  modelID: 9, name: 'Odyssey'}, 
                { makeID: 5,  modelID: 10, name: 'Camry'}, 
                { makeID: 5,  modelID: 11, name: 'Corolla'}
            ]
            // 
            // Put this in a stand alone .js file
            //
            // returns array of elements whose 'prop' property is 'value' 
            function filterByProperty(arr, prop, value) { 
                return $.grep(arr, function (item) { return item[prop] == value }); 
            } 
            // populates select list from array of items given as objects: { name: 'text', value: 'value' } 
            function populateSelect(el, items) { 
                el.options.length = 0; 
                if (items.length > 0) 
                    el.options[0] = new Option('please select', ''); 
                $.each(items, function () { 
                    el.options[el.options.length] = new Option(this.name, this.value); 
                }); 
            }  
            // initialization 
            $(document).ready(function () { 
                // populating 1st select list 
                populateSelect($('#sType').get(0), $.map(types, function(type) { return { name: type.name, value: type.typeID} }));      
                 // populating 2nd select list 
                $('#sType').bind('change', function() { 
                    var theModels = filterByProperty(makes, 'typeID', this.value);
                    populateSelect($('#sMake').get(0), $.map(theModels, function(make) { return { name: make.name, value: make.makeID} })); 
                    $('#sMake').trigger('change'); 
                }); 
                 // populating 3nd select list 
                $('#sMake').bind('change', function() { 
                    var theSeries = filterByProperty(model, 'makeID', this.value);  
                    populateSelect($('#sModel').get(0), $.map(theSeries, function(model) { return { name: model.name, value: model.modelID} })); 
                }); 
            });
        </script>
      </head>
      <body>
        Enter values, click submit, and look at the post parameters
        <form method="get" action="index.php">
                <div id="selection"> 
                    <select id="sType" name="type_id" style="{width=75px}"></select> 
                    <select id="sMake"  name="make_id" style="{width=75px}"></select> 
                    <select id="sModel"  name="model_id" style="{width=75px}"></select> 
                </div>
                <input type="submit">
        </form>
      </body>
    </html>  
    

    Notice that my solution shifts the functionality so that Make-Model are the 2nd and 3rd text boxes, and Type ( domestic, import, boat, etc. ) are the 1st level. I got the boilerplate JS down to 23 lines (less comments) while retaining good formatting.

    The JSON data is very easy to render from SQL queries, which are cached in java Lists on init because the Type-Make-Model rarely change. I don't use any dynamic AJAX because that complicates the architecture, and I have a relatively small list of available values, so I just send it at the page request.

    "Solutions should be a simple as possible, but no simpler" - A. Einstein

    0 讨论(0)
  • 2020-11-28 04:32

    Thanks to the answer from @Marko Dunic, I was able to build an array (data) structure that can be referenced to populate 3 select boxes. I didn't use the implementation code only because I didn't completely understand it...it works as posted. I will come back to this code later as I learn jQuery. My code is posted below (obviously, your reference to jQuery may be different)

    <html><head>
    <script language="Javascript" src="javascript/jquery-1.2.6.min.js"></script>
    <script type="text/JavaScript">
    var cars = [
    { name: 'Honda', models: [
    { name: 'Accord', features: ['2dr', '4dr'] },
    { name: 'CRV', features: ['2dr', 'Hatchback'] },
    { name: 'Pilot', features: ['base', 'superDuper'] }
       ]},
    { name: 'Toyota', models: [
    { name: 'Prius', features: ['green', 'superGreen'] },
    { name: 'Camry', features: ['sporty', 'square'] },
    { name: 'Corolla', features: ['cheap', 'superFly'] }
       ]
     }
    ];
    $(function() {
    var options = '' ;
    for (var i = 0; i < cars.length; i++) {
        var opt = cars[i].name ;
        if (i == 0){  options += '<option selected value="' + opt + '">' + opt + '</option>'; }
        else {options += '<option value="' + opt + '">' + opt + '</option>'; } 
    }
    $("#maker").html(options);   // populate select box with array
    
    var options = '' ;
    for (var i=0; i < cars[0].models.length; i++) { 
        var opt = cars[0].models[0].name ;
        if (i==0){options += '<option selected value="' + opt + '">' + opt + '</option>';}
        else {options += '<option value="' + opt + '">' + opt + '</option>';} 
    }
    $("#model").html(options);   // populate select box with array
    
    var options = '' ;
    for (var i=0; i < cars[0].models[0].features.length; i++) { 
        var opt = cars[0].models[0].features[i] ;
        if (i==0){options += '<option selected value="' + opt + '">' + opt + '</option>';}
        else {options += '<option value="' + opt + '">' + opt + '</option>';}
    }
    $("#feature").html(options);   // populate select box with array
    
    $("#maker").bind("click",
        function() {
            $("#model").children().remove() ;       // clear select box
            for(var i=0; i<cars.length; i++) {
                if (cars[i].name == this.value) {
                    var options = '' ;
                    for (var j=0; j < cars[i].models.length; j++) { 
                        var opt= cars[i].models[j].name ;
                        if (j==0) {options += '<option selected value="' + opt + '">' + opt + '</option>';}
                        else {options += '<option value="' + opt + '">' + opt + '</option>';} 
                    }
                    break;
                }
            }
            $("#model").html(options);   // populate select box with array
    
            $("#feature").children().remove() ;     // clear select box
            for(var i=0; i<cars.length; i++) {
                for(var j=0; j<cars[i].models.length; j++) {
                    if(cars[i].models[j].name == $("#model").val()) {
                        var options = '' ;
                        for (var k=0; k < cars[i].models[j].features.length; k++) { 
                            var opt = cars[i].models[j].features[k] ;
                            if (k==0){options += '<option selected value="' + opt + '">' + opt + '</option>';}
                            else {options += '<option value="' + opt + '">' + opt + '</option>';}
                        }
                        break;
                    }
                }
            }
            $("#feature").html(options);   // populate select box with array
        });
    
        $("#model").bind("click",
            function() {
                $("#feature").children().remove() ;     // clear select box
                for(var i=0; i<cars.length; i++) {
                    for(var j=0; j<cars[i].models.length; j++) {
                        if(cars[i].models[j].name == this.value) {
                            var options = '' ;
                            for (var k=0; k < cars[i].models[j].features.length; k++) { 
                                var opt = cars[i].models[j].features[k] ;
                                if (k==0){options += '<option selected value="' + opt  + '">' + opt  + '</option>';}
                                else {options += '<option value="' + opt  + '">' + opt  + '</option>';}
                            }
                            break ;
                        }
                    }
                }
                $("#feature").html(options);   // populate select box with array
        });
    });
    </script>
    </head> <body>
    <div id="selection">
    <select id="maker"size="10" style="{width=75px}"></select>
    <select id="model" size="10" style="{width=75px}"></select>
    <select id="feature" size="10"style="{width=75px}"></select>
    </div></body></html>
    
    0 讨论(0)
  • 2020-11-28 04:36

    I prefer data structure like this:

    var carMakers = [
        { name: 'Honda', models: [
                { name: 'Accord', features: ['2dr', '4dr'] },
                { name: 'CRV', features: ['2dr', 'Hatchback'] },
                { name: 'Pilot', features: ['base', 'superDuper'] }
            ]},
    
        { name: 'Toyota', models: [
                { name: 'Prius', features: ['green', 'superGreen'] },
                { name: 'Camry', features: ['sporty', 'square'] },
                { name: 'Corolla', features: ['cheap', 'superFly'] }
            ]}
    ];
    

    Given the three select lists with id's: 'maker', 'model' and 'features' you can manipulate them with this (I believe this is pretty self explanatory):

    // returns array of elements whose 'prop' property is 'value'
    function filterByProperty(arr, prop, value) {
        return $.grep(arr, function (item) { return item[prop] == value });
    }
    
    // populates select list from array of items given as objects: { name: 'text', value: 'value' }
    function populateSelect(el, items) {
        el.options.length = 0;
        if (items.length > 0)
            el.options[0] = new Option('please select', '');
    
        $.each(items, function () {
            el.options[el.options.length] = new Option(this.name, this.value);
        });
    }
    
    // initialization
    $(document).ready(function () {
        // populating 1st select list
        populateSelect($('#maker').get(0), $.map(carMakers, function(maker) { return { name: maker.name, value: maker.name} }));
    
        // populating 2nd select list
        $('#maker').bind('change', function() {
            var makerName = this.value,
                carMaker = filterByProperty(carMakers, 'name', makerName),
                models = [];
    
            if (carMaker.length > 0)
                models = $.map(carMaker[0].models, function(model) { return { name: model.name, value: makerName + '.' + model.name} });
    
            populateSelect($('#model').get(0), models);
            $('#model').trigger('change');
        });
    
        // populating 3rd select list
        $('#model').bind('change', function () {
            var nameAndModel = this.value.split('.'),
                features = [];
    
            if (2 == nameAndModel.length) {
                var makerName = nameAndModel[0], 
                    carModel = nameAndModel[1],
                    carMaker = filterByProperty(carMakers, 'name', makerName);
    
                if (carMaker.length > 0) {
                    var model = filterByProperty(carMaker[0].models, 'name', carModel)
    
                    if (model.length > 0)
                        features = $.map(model[0].features, function(feature) { return { name: feature, value: makerName + '.' + carModel + '.' + feature} })
                }
            }
    
            populateSelect($('#feature').get(0), features);
        })
    
        // alerting value on 3rd select list change
        $('#feature').bind('change', function () { 
            if (this.value.length > 0)
                alert(this.value);
        })
    });
    
    0 讨论(0)
  • 2020-11-28 04:36

    You should take a look here for select box manipulation. For what you want, i think JSON will do the right job for you. Anyhow, if i were you, i will do this way: When I change first select, i do an ajax request. With ajax response, i will populate the second box. Same for second box and there you have the third box populated with right data.

    0 讨论(0)
提交回复
热议问题