Использование javascript и jquery для заполнения связанных полей выбора структурой массива - PullRequest
23 голосов
/ 08 октября 2008

Используя ответы на этот вопрос , я смог заполнить поле выбора на основе выбора другого поля выбора. ( Я разместил свой ответ здесь ) Извлечение данных из структуры массива, построенной на стороне сервера, сохраненной в файле .js и указанной на html-странице.

Теперь я хотел бы добавить третье поле выбора. Если бы у меня было 3 набора данных (модель, марка, опции) примерно так (псевдокод):

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

Пример: Если бы была выбрана Honda, в следующем поле выбора было бы [Accord Civic], а если бы было выбрано Accord, в следующем поле выбора было бы [Lx Dx]

Как я могу

1) создать структуру массива для хранения данных? такой, что

2) Я могу использовать значение из одного поля выбора, чтобы ссылаться на необходимые значения для следующего поля выбора

Спасибо

EDIT

Я могу создать следующее, но не могу определить ссылки таким образом, чтобы это помогло заполнить поле выбора

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

Ответы [ 4 ]

45 голосов
/ 08 октября 2008

Я предпочитаю такую ​​структуру данных:

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'] }
        ]}
];

Учитывая три списка выбора с идентификаторами: «производитель», «модель» и «функции», вы можете манипулировать ими с помощью этого (я считаю, что это само собой разумеется):

// 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);
    })
});
3 голосов
/ 09 октября 2008

Благодаря ответу @Marko Dunic я смог построить структуру массива (данных), на которую можно ссылаться, чтобы заполнить 3 поля выбора. Я не использовал код реализации только потому, что не до конца его понял ... он работает так, как написано. Я вернусь к этому коду позже, когда буду изучать jQuery. Мой код размещен ниже (очевидно, ваша ссылка на 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>
2 голосов
/ 25 октября 2011

Мне очень понравилось решение @Marko Dunic, но оно не соответствовало моим потребностям в прикреплении идентификаторов к опциям. Как только я прикрепил идентификаторы, я понял, что могу сделать код JS еще меньше и проще. Мое решение предназначено для случаев, когда данные поступают из реляционной базы данных, а входные данные JSON сохраняют реляционную структуру с первичными / внешними ключами. Вот данные 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>  

Обратите внимание, что мое решение меняет функциональность так, что Make-Model - это 2-е и 3-е текстовые поля, а Type (внутренний, импортный, судовой и т. Д.) - 1-й уровень. Я сократил шаблон JS до 23 строк (меньше комментариев), сохранив хорошее форматирование.

Данные JSON очень легко визуализировать из запросов SQL, которые кэшируются в списках java при инициализации, поскольку Type-Make-Model редко изменяется. Я не использую динамический AJAX, потому что это усложняет архитектуру, и у меня есть сравнительно небольшой список доступных значений, поэтому я просто отправляю его по запросу страницы.

«Решения должны быть максимально простыми, но не более простыми» - А. Эйнштейн

1 голос
/ 08 октября 2008

Вы должны взглянуть здесь для выбора блока манипуляции. Для того, что вы хотите, я думаю, JSON сделает правильную работу для вас. Во всяком случае, если бы я был тобой, я бы сделал так: Когда я меняю первый выбор, я делаю запрос ajax. С ответом ajax я заполню второе поле. То же самое для второго блока, и там у вас есть третий блок, заполненный правильными данными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...