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

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

Медицинские услуги
— Услуга 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
modx.pro
6
3 045
0

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

Владислав
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
      3
      +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 апреля 2023, 16:38
            0
            сделал по аналогии
            файл
            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';
            		$snippetParams['showUnpublished'] = '1';
            		$snippetParams['depth'] = '0';
            
            		//Дописать параметры для сниппета получающего результаты по вкусу			
            
            		$snippetResult = $modx->runSnippet('pdoResources', $snippetParams);
            
            		$result = array($snippetResult, 'success');
            	}
            	else {
            		$result = array('Некорректный запрос', 'error');
            	}
            	
            	if (!empty($result)) {
            		die(json_encode($result));
            	}
            скрипт
            <script type="text/javascript">
                	$(document).on('change', 'select[name="vid_vzn"]', function(e) {
                		if ($(this).val() != '') {
                    			$.ajax({
                    				type: "POST",
                    				url: "assets/lk/getlist.php",
                    				data: {
                    				    action: 'getList', 
                    				    parent: $("select[name='vid_vzn']").val()
                       		         },
            
                    			success: function(response) {
                    				var data = eval(response);
                    
                    				switch (data[1]) {
                    					case 'success':
                						//Если все ок - вставляем результат во второй селектор
                						$("select[name='god']").val("").html("<option value='' selected disabled>Выберите значение из списка</option>" + data[0])
                
                    						break;
                   							
                    						
                    					}
                    				}
                    			});
                		}
                	});
                </script>
            html
            <div class="form-group">
            		<label for="vid_vzn" class="col-sm-4 control-label">Вид взноса</label>
            		<div class="col-sm-8">
            			 <select class="form-control" name="vid_vzn" id="vid_vzn">
            			 [[!pdoResources?
            			    &parents=`1469`
            			    &depth=`0`
            			    &limit=`0`
            			    &showUnpublished=`1`
            			    &tpl=`@INLINE <option value="[[+id]]">[[+pagetitle]]</option>`
            			    &sortby=`pagetitle`
            			    &sortdir=`ASC`
            			]]
            			 </select>
            		</div>
            	</div>
            	<div class="form-group">
            		<label for="god" class="col-sm-4 control-label">Выберите год</label>
            		<div class="col-sm-8">
            			<select name="god">
            			    <option value="" selected disabled>Год</option>
            			</select>
            		</div>
            	</div>
            удалил вот это кусок, он у меня ошибку вызвал, по идее если все норм он не должен влиять на работу.
            case 'error':
            							//Если не ок - выводим ошибку (используется jGrowl)
                							$.jGrowl(data[0], {theme: 'error', position: 'center'});
                							
                							break;
            при переключении первого списка появляется только вот это «Выберите значение из списка», а сам список пустой.
            элементы неопубликованные и контейнеры, но я вроде бы добавил параметры чтобы они попадали в выборку, да и пробовал публиковать — все равно ничего не дает.
            Сергей Шлоков
            08 августа 2016, 11:05
            0
            Самый простой и самый быстрый вариант — выводить полный список и услуг и врачей, а яваскриптом скрывать ненужные пункты. Единственный момент — защита от дурака/хулигана — при сохранении проверять соответствие врача услуге по родителю.
              Владимир
              10 сентября 2018, 20:49
              0
              Ребята, решение отличное! Поставил работает четко, но нужна ваша помощь по скрипту. Использую данное решение для онлайн калькулятора с плагином jAutoCalc, при использовании функции добавить новую форму расчета он копирует контейнер первого без заполненных полей, так вот, класс контейнера и имена селектов естественно не меняють и при выборе в новой скопированной форме первого селекта, второй селект обновляеться в обоих формах, возможно привязать данное действие передачи информации с первого во второй селект с привязкой действия к родительскому контейнеру каждой формы? При копировании форм код получаеться такой:
              [[!pdoMenu?
                      &level=`1`
                      &parents=`2`
                      &tplOuter=`@INLINE [[+wrapper]]`
                      &tpl=`@INLINE <option value="[[+id]]">[[+menutitle]]</option>`
                      &toPlaceholder=`selector-1`
                  ]]
              <form name="form-calc">
                  
              Основная форма
              
                  <div class="line_items">
                      <select name="selector-1">
                          <option selected disabled>Выберите услугу</option>
                          [[+selector-1]]
                      </select>
                      <select name="selector-2">
                          <option value="" selected disabled>Выберите врача</option>
                      </select>
                  </div>
              
              Первая копия
              
                  <div class="line_items">
                      <select name="selector-1">
                          <option selected disabled>Выберите услугу</option>
                          [[+selector-1]]
                      </select>
                      <select name="selector-2">
                          <option value="" selected disabled>Выберите врача</option>
                      </select>
                  </div>
              
              Вторая копия
              
                  <div class="line_items">
                      <select name="selector-1">
                          <option selected disabled>Выберите услугу</option>
                          [[+selector-1]]
                      </select>
                      <select name="selector-2">
                          <option value="" selected disabled>Выберите врача</option>
                      </select>
                  </div>
              
                  и т.д.
              
              </form>
                Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                16