Как сделать динамический зависимый список ресурсов

Имеется следующая структура:

Медицинские услуги
— Услуга 1
— — Врач 1
— — Врач 2
— Услуга 2
— — Врач 3
— — Врач 4
— Услуга 3
— — Врач 5
— — Врач 6

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


В данный момент первый список генерируется так:
<select name="usluga" class="service-select">
	<option value="" selected>Выберите услугу</option>
	[[!pdoMenu?
		&level=`1`
		&parents=`2`
		&tpl=`tpl.uslugaItem`
	]]
</select>

Код чанка tpl.uslugaItem:
<option value="[[+menutitle]]">[[+menutitle]]</option>
Александр
08 августа 2016, 06:46
4
1 188
0

Комментарии: 14

Владислав
08 августа 2016, 10:13
0
так же. только в parents вставь текущий id
&parents=`[[*id]]`
Дмитрий Середюк
08 августа 2016, 10:14
0
я так понимаю вам нужно что то подобное?
[[!pdoMenu?
&parents=`2`
&level=`2`
&firstClass=`0`
&lastClass=`0`
&hereClass=`0`
&outerClass=`0`
&tplOuter=`@INLINE [[+wrapper]]`
&tpl=`@INLINE <optgroup label="[[+menutitle]]">[[+wrapper]]</optgroup>`
&tplInner=`@INLINE [[+wrapper]]`
&tplInnerRow=`tpl.uslugaItem`
]]
то есть родителя обрамлять в тег optgroup, а именно услуги.

в чанке tpl.uslugaItem необходимо использовать сниппет UltimateParent или pdoField в результате должно получится как то так:

<option [[+id:is=`[[UltimateParent? id=`[[+id]]` &topLevel=`3`]]`:then=`selected`]] value="[[+id]]">[[+menutitle]]</option>

где parents=`2` родительский ресурс в котором находятся услуги -> врачи…
    Александр
    08 августа 2016, 10:35
    0
    Не совсем. Нужно динамически добавлять список врачей во второй селектбокс, после выбора услуги из первого.

    s6221.h6.modhost.pro
Максим Кузнецов
08 августа 2016, 10:34
1
+3
Реализовать ajax-запрос. Примерно вот так:

1. Вешаем на событие переключения селектора скрипт, который будет выполнять ajax-запрос:
<script>
	var canClick = true;

	$(document).on('change', 'select[name="selector-1"]', function(e) {
		if ($(this).val() != '' && canClick = true) {
    			$.ajax({
    				type: "POST",
    				url: "assets/ajax/getlist.php",
    				data: {
    					action: 'getList', 
    					parent: $("select[name='selector-1']").val()
       		        	},
    			
    				beforeSend: function(){
					canClick = false;
    				},
    			
    				success: function(response) {
    					var data = eval(response);
    
    					switch (data[1]) {
    						case 'success':
							//Если все ок - вставляем результат во второй селектор
							$("select[name='selector-2']").html("<option value='' selected disabled>Выберите значение из списка</option>" + data[0]).val("");

    							break;
    							
    						case 'error':
							//Если не ок - выводим ошибку (используется jGrowl)
    							$.jGrowl(data[0], {theme: 'error', position: 'center'});
    							
    							break;
    						
    					}

					canClick = true;
    				}
    			});
		}
	});
</script>

2. Создаем файл (в моем примере assets/ajax/getlist.php), на который ссылается скрипт и который будет возвращать нам результат:
<?php
	if ($_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest' || empty($_POST['action'])) {
		return;
	}

	define('MODX_API_MODE', true);

	require dirname(dirname(dirname(__FILE__))) . '/index.php';
	
	$modx->getService('error','error.modError');
	$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
	$modx->setLogTarget('FILE');
	
	
	if ($_POST['action'] == "getList" && isset($_POST['parent'])) {
		//Получаем значение для второго селектора
		$snippetParams = array();
		$snippetParams['parents'] = intval($_POST['parent']);
		$snippetParams['tpl'] = '@INLINE <option value="[[+menutitle]]">[[+menutitle]]</option>';
		//Дописать параметры для сниппета получающего результаты по вкусу			

		$snippetResult = $modx->runSnippet('pdoResources', $snippetParams);

		$result = array($snippetResult, 'success');
	}
	else {
		$result = array('Некорректный запрос', 'error');
	}
	
	if (!empty($result)) {
		die(json_encode($result));
	}
    Александр
    08 августа 2016, 10:55
    0
    Спасибо, но что-то пока не заводится… s6221.h6.modhost.pro
    И ошибку никакую не пишет даже.
      Максим Кузнецов
      08 августа 2016, 10:58
      0
      Это потому что у вас parent отправляется не как id родителя, а как «Услуга 1». Замените чанк:
      <option value="[[+menutitle]]">[[+menutitle]]</option>
      на такой:
      <option value="[[+id]]">[[+menutitle]]</option>
        Александр
        08 августа 2016, 11:11
        0
        Заменил. К сожалению, пока тот же результат.
          Максим Кузнецов
          08 августа 2016, 11:12
          0
          Скиньте доступы, если не затруднит.

          Ну или проверьте сами, пожалуйста — у вас точно есть данная строка в php-файле:
          $result = array($snippetResult, 'success');
            Александр
            08 августа 2016, 11:20
            0
            Отправил доступы
              Максим Кузнецов
              08 августа 2016, 11:24
              0
              Готово. =)
                Александр
                08 августа 2016, 11:29
                1
                0
                Вижу) спасибо огромное!
                Если кому нужно, выкладываю скрипты:

                Файл getlist.php
                <?php
                	if ($_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest' || empty($_POST['action'])) {
                		return;
                	}
                
                	define('MODX_API_MODE', true);
                
                	require dirname(dirname(dirname(__FILE__))) . '/index.php';
                	
                	$modx->getService('error','error.modError');
                	$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
                	$modx->setLogTarget('FILE');
                	
                	
                	if ($_POST['action'] == "getList" && isset($_POST['parent'])) {
                		//Получаем значение для второго селектора
                		$snippetParams = array();
                		$snippetParams['parents'] = intval($_POST['parent']);
                		$snippetParams['tpl'] = 'option.item';
                		//Дописать параметры для сниппета получающего результаты по вкусу			
                
                		$snippetResult = $modx->runSnippet('pdoResources', $snippetParams);
                
                		$result = array($snippetResult, 'success');
                	}
                	else {
                		$result = array('Некорректный запрос', 'error');
                	}
                	
                	if (!empty($result)) {
                		die(json_encode($result));
                	}

                javascript:
                <script type="text/javascript">
                    	$(document).on('change', 'select[name="selector-1"]', function(e) {
                    		if ($(this).val() != '') {
                        			$.ajax({
                        				type: "POST",
                        				url: "assets/ajax/getlist.php",
                        				data: {
                        				    action: 'getList', 
                        				    parent: $("select[name='selector-1']").val()
                           		         },
                
                        			success: function(response) {
                        				var data = eval(response);
                        
                        				switch (data[1]) {
                        					case 'success':
                    						//Если все ок - вставляем результат во второй селектор
                    						$("select[name='selector-2']").val("").html("<option value='' selected disabled>Выберите значение из списка</option>" + data[0])
                    
                        						break;
                        							
                        					case 'error':
                    						//Если не ок - выводим ошибку (используется jGrowl)
                        						$.jGrowl(data[0], {theme: 'error', position: 'center'});
                        							
                        						break;
                        						
                        					}
                        				}
                        			});
                    		}
                    	});
                    </script>

                Ну и html понятно:
                <select name="selector-1">
                    <option selected disabled>Выберите услугу</option>
                    [[!pdoMenu?
                    	&level=`1`
                    	&parents=`2`
                    	&tplOuter=`@INLINE [[+wrapper]]`
                    	&tpl=`@INLINE <option value="[[+id]]">[[+menutitle]]</option>`
                    ]]
                </select>
                <select name="selector-2">
                    <option value="" selected disabled>Выберите врача</option>
                </select>
                  Максим Кузнецов
                  08 августа 2016, 11:31
                  +1
                  Да я, честно говоря, и скопировал свой же код из поста выше — видимо, вы его вставили до моей редакции..)

                  Ну и содержимое Inline-чанка вынес в полноценный чанк + canClick убрал, вот и все.
    Александр
    08 августа 2016, 10:57
    0
    В 4й строке
    if ($(this).val() != '' && canClick = true) {
    пришлось поменять на
    if ($(this).val() != '' && canClick == true) {
    ругался браузер.

    Но всё равно не работает
Сергей Шлоков
08 августа 2016, 11:05
0
Самый простой и самый быстрый вариант — выводить полный список и услуг и врачей, а яваскриптом скрывать ненужные пункты. Единственный момент — защита от дурака/хулигана — при сохранении проверять соответствие врача услуге по родителю.