О web-разработке
и даже немного больше...

Как реализовать 3 и более зависимых списка?

zavisimye-spiski
Некоторое время назад в нашем блоге публиковался пост о том, как сделать зависимые списки на JQuery/Ajax. В той статье был опубликован пример реализации двух списков, т.е. кода один список имеет зависимость от другого. Очевидно, для задач со списками более двух пришлось переделать скрипт, чтобы получить желаемый результат.
По этой теме ранее в комментариях был задан вопрос, о том, как реализовать 3 зависимых списка, при котором третий зависит от второго, второй от первого. В общем, пробуем делать 3 списка с зависимостями. Первым делом меняем структуру массива, в которых хранились наши данные, такой метод хранения позволит реализовать сколько угодно вложенностей в дальнейшем.
Допустим, у нас есть данные такой структуры:

BMW
--5-series
----518
----525
----530
--7-series
----720
----730
----740
----750
Mercedes-Benz
--C-класс
----C 160
----C 180
--E-класс
----C 200
----E 220
----E 230

В массиве разбиваем данные списка на уровни, плюс дополнительный параметр parent, который будет указывать на ключ в родительском списке.

$arParams = array(
	'models' => array(
		0 => 'BMW',
		1 => 'Mercedes-Benz'
	),
	'series' => array(
		0 => array('value' => '5-series' ,'parent' => 0),
		1 => array('value' => '7-series' ,'parent' => 0),
		2 => array('value' => 'C-класс', 'parent' => 1),
		3 => array('value' => 'E-класс', 'parent' => 1),
	),
	'modif' => array(
		0 => array('value' => '518', 'parent' => 0),
		1 => array('value' => '525', 'parent' => 0),
		2 => array('value' => '530', 'parent' => 0),
		3 => array('value' => '720', 'parent' => 1),
		4 => array('value' => '730', 'parent' => 1),
		5 => array('value' => '740', 'parent' => 1),
		6 => array('value' => '740', 'parent' => 1),
		7 => array('value' => 'C 160', 'parent' => 2),
		8 => array('value' => 'C 180', 'parent' => 2),
		9 => array('value' => 'C 230', 'parent' => 2),
		10 => array('value' => 'E 200', 'parent' => 3),
		11 => array('value' => 'C 220', 'parent' => 3),
		12 => array('value' => 'C 230', 'parent' => 3),
	)
);

Как и прежде, отдавать данные форме мы будет в ajax формате, однако в скрипте ajax.php пришлось сделать кардинальные изменения. Для получения данных скрипту нужно передать два параметра, listName и id. В listName передается параметр, который указывает на ключ массива, из которого запрашиваются элементы, в нашем примере это series – запрос серий модели и modif – запрос модификаций серии. Параметр id – указывает значение ключа в родительском списке.

<?php
require_once('cars.php');
$arResult = array();

if (isset($_GET['listName']) &&
	array_key_exists($_GET['listName'],$arParams) &&
	isset($_GET['id']) && is_numeric($_GET['id'])){
		foreach ($arParams[$_GET['listName']] as $id => $arItems){
			if ($arItems['parent'] == $_GET['id'])
				$arResult[$id] = $arItems;
		}
}
echo json_encode ($arResult);
?>

Кроме того, сама форма так же поменялась:

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<select name="models" onchange="loadCar('models','series')">
<option>Модель</option>
<?php
require_once('cars.php');
foreach ($arParams['models'] as $mid => $model)
	echo '<option value="' . $mid . '">' . $model . '</option>' . "\n";
?>
</select>
<select name="series" onchange="loadCar('series','modif');"><option>Серия</option></select>
<select name="modif"><option>Модификация</option></select>


<script>
function loadCar(parent,child){
	parentSel = $('select[name="'+parent+'"] option:selected');
	childSel = $('select[name="'+child+'"]');
	switch (parent){
		case 'models':
			$('select[name="series"]').html('<option>Серия</option>');
			$('select[name="modif"]').html('<option>Модификация</option>');
		break;
		case 'series':
			$('select[name="modif"]').html('<option>Модификация</option>');
		break;
	}
	if (isInt(parentSel.val())){
		$.getJSON('ajax.php', {
			listName:child,
			id:parentSel.val()
		}, function(Items){
			$.each(Items, function(i){
				childSel.append('<option value="'+i+'">' + this.value + '</option>');
			});
		});
	}
}
function isInt(n){ return n % 1 === 0; }
</script>


В итоге можно посмотреть ПРИМЕР того что получилось, а вот ИСХОДНИКИ примера.

Опубликован: 23.03.2015 г.

См. также:

Загрузка файлов на сервер посредством Ajax
Отложенная загрузка изображений Lazy Load
Анимация набора текста на Typed.js
Анимация отсчёта на jquery-spincrement
Mega Dropdown — Меню для мобильной версии
Отслеживаем клик вне элемента на JQuery
Ajax-загрузка записей при скроллинге и нажатии кнопки
Stimed – задаем CSS-стили по времени

Комментарии

  1. woodyfon пишет:

    Как изменить код так, чтобы содержимое второго и третьего списков не выводилось до тех пор, пока не выбран пункт в первом и во втором соответственно? Так будет логичнее.

    1. htmaker пишет:

      Пример зависимого списка в твоём случае. Изначально добавляем в CSS для вложенных списков значение display:none а уже после в js включаем показ при выборе значений.

  2. Igor пишет:

    Здравствуйте, как быть если используется в value не целые значения а с разделителем - точкой (реализация для калькулятора)

    'models' => array(
    '0' => 'BMW',
    '1' => 'Rolls Roys',
    ),
    'series' => array(
    '1.18' => array('value' => 'Механика','parent' => '0'),
    '1.15' => array('value' => 'Автомат','parent' => '0'),
    ),
    'modif' => array(
    '0' => array('value' => '2500000руб.', 'parent' => '1.18'),
    '1' => array('value' => '1500000руб.', 'parent' => '1.15'),
    )

    1. htmaker пишет:

      Здравствуйте, можете описать задачу детальнее?

      1. Igor пишет:

        У меня калькулятор считает по значению value (это реализовано), но не могу реализовать что бы parent был равен к примеру 1.15, пример кода выше

        1. htmaker пишет:

          Понятно, закоментируйте условие проверки на целочисленное значение:
          if (isInt(parentSel.val())){
          ...

          См. пример выше, условие находится на 27 строке

          1. Igor пишет:

            Как оказывается все элементарное - просто! Спасибо огромное. Удачи и процветания Вашему блогу!

          2. htmaker пишет:

            спасибо!)

  3. info пишет:

    Если нужно добавить дополнительный 4 и 5 зависимый список?!

    1. htmaker пишет:

      Добавляешь select с параметрами onchange, а так же новый элемент в массиве PHP.

  4. Александр пишет:

    Довольно простой и понятный пример!
    Немного переписать и можно дёргать с БД.

    Спасибо!

  5. Александр пишет:

    cars.php

    $q=mysql_query("SELECT * FROM `cars` WHERE `selector`='1' ORDER BY `id` ASC");
    while($f=mysql_fetch_assoc($q)){
    $arParams['models'][$f['id']] = $f['name'];
    }
    $q=mysql_query("SELECT * FROM `cars` WHERE `selector`='2' ORDER BY `id` ASC");
    while($f=mysql_fetch_assoc($q)){
    $arParams['series'][$f['id']]=array('value' => $f['name'],'parent' => $f['id_pod_menu']);
    }
    $q=mysql_query("SELECT * FROM `cars` WHERE `selector`='3' ORDER BY `id` ASC");
    while($f=mysql_fetch_assoc($q)){
    $arParams['modif'][$f['id']]=array('value' => $f['name'],'parent' => $f['id_pod_menu']);
    }

    Спасиб ещё раз.

    1. Александр пишет:

      опечатка
      WHERE `selector`='1'
      WHERE `selector`='2'
      WHERE `selector`='3'

  6. Торба пишет:

    Всем привет. Возник вопрос. Как при выборе последнего селекта перенаправить на юрл?

  7. Торба пишет:

    И еще, можно пример дампа бд выложить))

  8. Айнур пишет:

    Здравствуйте, как реализовать следующую ситуацию у меня количество селектов отличается, где-то 3 уровня, где-то 5 уровней. как сделать так, чтобы это учитывалось и если мало уровней, то пустые уровни просто не показывались

    1. htmaker пишет:

      Айнур, в вашем случае более правильно использовать рекурсию. Проверять длину массива возвращаемого с сервера, если длина == 0, то не показывать список.

  9. Михаил пишет:

    Привет! Респект! Очень круто и понятно.
    Вопрос такой: я создал зависимые списки, все работает. Вношу правки (добавляю данные) и при обычном обновлении данные не подтягиваются. Только когда сбросишь кеш либо зайдешь с другого браузера. Как решить эту проблему?

    И еще вопрос, который уже задавали:
    Как при выборе последнего селекта перенаправить на юрл?

    1. htmaker пишет:

      1. Просмотрите в консоли браузера, происходит ли запрос к скрипту на сервере, возможно возникают ошибки на стороне браузера;
      2. Пропишите условие в js для редиректа.

      1. Михаил пишет:

        1. Исправил. Спасибо
        2. Мне нужно сделать как тут: http://www.orafol.com/gp/europe/en/icc-profiles в конце появляется кнопка для скачивания профиля по параметрам выше. Что-то не догоняю как это реализовать...

      2. Михаил пишет:

        Посмотри, что я сделал: https://yadi.sk/i/SPVA6CNa3FfSMv

  10. Игорь пишет:

    Круто ! но вот у меня проблемка, выбор марки подгружается, во втором списке появляется "Серия" и больше ничего нету... код в стоке лишь "require_once" с путем в мою папку. Пробовал от прошлого урока с двумя списками - все отлично работает, в чем может быть проблема?

  11. Марк пишет:

    здравствуйте. скажите пожалуйста, а где это надо все прописать в php? html? как это реализовать? я только начал работать над этим.

  12. Анатолий пишет:

    У меня кв массиве есть ещё ссылки на соответствующие страницы. В форме у меня есть кнопка. Нужно, чтобы после выбора модификации в кнопку подгружалась ссылка соответствующая этой модификации. Подскажите, как это реализовать?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Комментарии
  • Загрузка...
Друзья сайта