简体   繁体   English

使用javascript和jquery,用数组结构填充相关的选择框

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

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 array structure built server-side, stored in a .js file and referenced in the html page. 我在这里发布了我的答案 )从服务器端构建的数组结构中提取数据,存储在.js文件中并在html页面中引用。

Now I would like to add a third select box. 现在我想添加第三个选择框。 If I had 3 sets of data (model, make, options) something like this (pseudo code): 如果我有3组数据(模型,制作,选项)类似这样(伪代码):

cars : [Honda[Accord[Lx, Dx]], [Civic[2dr, Hatchback]],
   [Toyota[Camry[Blk, Red]], [Prius[2dr,4dr]]

Ex: If Honda were selected, the next select box would have [Accord Civic] and if Accord were selected the next select box would have [Lx Dx] 例如:如果选择本田,下一个选择框将具有[Accord Civic],如果选择了Accord,则下一个选择框将具有[Lx Dx]

How can I 我怎么能够

1) create an array structure to hold the data? 1)创建一个数组结构来保存数据? such that 这样的

2) I can use the value from one select box to reference the needed values for the next select box 2)我可以使用一个选择框中的值来引用下一个选择框所需的值

Thanks 谢谢

EDIT 编辑

I can create the following, but can't figure out the references in a way that would help populate a select box 我可以创建以下内容,但无法以有助于填充选择框的方式找出引用

var cars = [
 {"makes"  : "Honda",
  "models"  : [
    {'Accord' : ["2dr","4dr"]} ,
    {'CRV'  : ["2dr","Hatchback"]} ,
    {'Pilot': ["base","superDuper"] } ]
 },
 {"makes"   :"Toyota",
  "models"  : [
    {'Prius'   : ["green","reallyGreen"]} ,
    {'Camry'   : ["sporty","square"]} ,
    {'Corolla' : ["cheap","superFly"] } ]
 } ] ;              

 alert(cars[0].models[0].Accord[0]); ---> 2dr

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): 给出带有id的三个选择列表:'maker','model'和'features',你可以用它来操作它们(我相信这是非常自我解释的):

// 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);
    })
});

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. 感谢@Marko Dunic的回答,我能够构建一个数组(数据)结构,可以引用它来填充3个选择框。 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. 我将在以后学习jQuery时回到这段代码。 My code is posted below (obviously, your reference to jQuery may be different) 我的代码发布在下面(显然,你对jQuery的引用可能有所不同)

<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>

I really liked the solution by @Marko Dunic, but it didn't meet my needs for attaching IDs to the options. 我非常喜欢@Marko Dunic的解决方案,但它不符合我将ID附加到选项的需求。 Once I attached the IDs, I realized that I could make the JS code even smaller and simpler. 一旦我附加了ID,我意识到我可以使JS代码更小更简单。 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. 我的解决方案是为数据来自关系数据库而设计的,JSON输入数据保留了与主/外键的关系结构。 Here is the JSON data: 这是JSON数据:

<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. 请注意,我的解决方案改变了功能,因此Make-Model是第2和第3个文本框,Type(国内,导入,船只等)是第1级。 I got the boilerplate JS down to 23 lines (less comments) while retaining good formatting. 我将样板JS减少到23行(减少注释),同时保留良好的格式。

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. JSON数据很容易从SQL查询中呈现,这些查询在init上的Java列表中缓存,因为Type-Make-Model很少更改。 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. 我不使用任何动态AJAX,因为这使架构复杂化,我有一个相对较小的可用值列表,所以我只是在页面请求发送它。

"Solutions should be a simple as possible, but no simpler" - A. Einstein “解决方案应尽可能简单,但不能简单” - 爱因斯坦

You should take a look here for select box manipulation. 您应该在这里查看选择框操作。 For what you want, i think JSON will do the right job for you. 对于你想要的,我认为JSON会为你做正确的工作。 Anyhow, if i were you, i will do this way: When I change first select, i do an ajax request. 无论如何,如果我是你,我会这样做:当我改变第一个选择时,我做一个ajax请求。 With ajax response, i will populate the second box. 使用ajax响应,我将填充第二个框。 Same for second box and there you have the third box populated with right data. 对于第二个框也是如此,并且您在第三个框中填充了正确的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM