Динамически изменять значение выпадающего списка

Вопрос или проблема

У меня есть форма, где я перечисляю связанный пользовательский тип постов по ID родительского пользовательского типа постов в виде списка чекбоксов, как на картинке.

Когда я отмечаю вариант из 4-х опций, я хочу получить список терминов, которые имеют пользовательские посты, которые я отметил в выпадающем списке.

Форма построена с помощью Elementor Pro, но чтобы получить список постов и терминов таксономии, я делаю это с помощью кода (я создаю свою функцию и подключаю её с помощью шорткода в functions.php).

/*
 * Отображение списка поля отношений
 *
*/

function list_formation_caces(){
echo "<div class="golistgo">";
$args = array(
    'post_type' => 'categories',
    'posts_per_page' => 20,
);
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post();
    $formations = get_posts(array(
        'post_type' => 'formations',
        'post__in' => array(16061),
        'meta_query' => array(
            array(
                'key' => 'categories', // имя пользовательского поля
                'value' => '"' . get_the_ID() . '"', // совпадает точно "123", а не просто 123. Это предотвращает совпадение для "1234"
                'compare' => 'LIKE'
            )
        )
    ));
    if($formations){
        foreach ($formations as $categorie){
            $image = get_field('image_form');
            if($image){
                // Переменные изображения.
                $url = $image['url'];
                $title = $image['title'];
                $alt = $image['alt'];
                $caption = $image['caption'];

                // Атрибуты размера миниатюры.
                $size="thumbnail";
                $thumb = $image['sizes'][ $size ];
                $width = $image['sizes'][ $size . '-width' ];
                $height = $image['sizes'][ $size . '-height' ];
            }
            echo "<input type=\"checkbox\" class=\"btn-check\" name=\"Description\" value =\"". get_the_title() .
                "\" id=\"". get_the_ID()  ."\">";
            echo "<label class=\"options-form\" for="". get_the_ID() ."">";
                               echo "<div class=\"image-cat\">";
                                    echo get_the_post_thumbnail();
                               echo"</div>";
                               echo "<div class=\"body-cat\">";
                                    echo "<div  class=\"title-formation\">" ;
                                    echo "</div>";
                                    echo "<div  class=\"title-cat\">" ;
                                    echo the_title() . ":" . " <span  class=\"describe-cat\">" . get_field('type_machine') . "</span>";
                                    echo "</div>";
                               echo "</div>";
            echo "</label>";
        }
    }
endwhile;
wp_reset_postdata();
echo "</div>";
}

function shortcode_list_categ_caces(){
            return (list_formation_caces()) ;
}
add_shortcode('list_formation_caces', 'shortcode_list_categ_caces');

function shortcode_total_count_checked(){

return ("<div class="count-checkboxes-wrapper">" . "<h2 class="title-count">" . "Вы выбрали" .
    "<span id='count-checked-checkboxes'> " . "  0" ."</span> категорию(и)."." </h2>" .
    "</div>");
}
add_shortcode('count_checked', 'shortcode_total_count_checked');

function list_sessions_caces()
{
    $terms = get_terms( array(
        'taxonomy' => 'sessions',
        'hide_empty' => false,
    ) );
    echo'<label for="form-field-centre" class="elementor-field-label">Где пройдет обучение?</label>';
    echo '<div class="elementor-field elementor-select-wrapper ">';
    echo '<select name="CENTRE"  id="form-field-field_centre" class="elementor-field-textual elementor-size-sm">';
    echo '<option value="">Выберите сессию обучения </option> ';
    foreach ($terms as $term) {
        echo '<option value="' . $term->name . '">' . $term->name . '</option>';
    }
    echo '</select>';
    echo'</div>';
}
function shortcode_list_sessions(){
    return (list_sessions_caces()) ;
}
add_shortcode('list_sessions_caces', 'shortcode_list_sessions');

Любая помощь, пожалуйста!
введите описание изображения здесь

Вы можете пойти двумя путями:

  1. Скорее всего, данных для таксономий обоих пользовательских типов постов не так много, поэтому вы могли бы отобразить эти два массива в javascript из php в вашем шаблоне, а затем переключать данные выпадающего списка по клику на чекбокс. Вы могли бы назвать массивы по id пользовательских типов постов, например cpt-134, а затем при клике на CPT установить данные выпадающего списка на массив с именем cpt-[id-пользовательского-типа-постов]. Один из способов получить эти данные в ваш javascript – это, если у вас, например, есть general.js:
wp_register_script('general', get_template_directory_uri() . '/js/general.js');
wp_localize_script('general', 'myVars', array(
  'site_url' => site_url(),
  'dropdownData' => get_CPT_Dropdown_Data(),
));
wp_enqueue_script('general');

Вам, конечно, придется написать эту функцию get_CPT_Dropdown_Data(), которая возвращает массивы с данными таксономий на основе id пользовательских типов постов.

  1. При клике на CPT вызовите ajax функцию, которую вы создали, чтобы получить таксономии для этого CPT. Затем обновите выпадающий список этими данными.

Второй вариант – это более надежный метод (если все расширится) и не наполняет ваш код данными, которые могут не понадобиться. Но это добавит дополнительные запросы к серверу, поэтому вы можете захотеть включить обратную связь для ваших пользователей, когда загрузка начнется.

Ответ или решение

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

Подход 1: Использование JavaScript и PHP для передачи данных

Первый подход подразумевает передачу данных с помощью JavaScript. Вы можете получить все необходимые данные из ваших пользовательских типов записей (CPT) при загрузке страницы и хранить их в JavaScript-объекте. Затем, когда пользователь выберет определенные опции, вы сможете изменять значения выпадающего списка на основе этих данных.

  1. Создание функции для получения данных о таксономиях:

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

    function get_CPT_Dropdown_Data() {
       $data = [];
       // Получите все ваши CPT и их таксономии здесь
       // Пример:
       $cpts = get_posts(array('post_type' => 'formations', 'numberposts' => -1));
       foreach ($cpts as $cpt) {
           $terms = get_the_terms($cpt->ID, 'sessions');
           if ($terms) {
               foreach ($terms as $term) {
                   $data[$cpt->ID][] = $term->name;
               }
           }
       }
       return $data;
    }
  2. Локализация скриптов:

    Теперь нужно зарегистрировать и локализовать ваш JavaScript файл, чтобы передать данные на клиентскую сторону.

    function enqueue_my_scripts() {
       wp_register_script('general', get_template_directory_uri() . '/js/general.js');
       wp_localize_script('general', 'myVars', array(
           'dropdownData' => get_CPT_Dropdown_Data(),
           'site_url' => site_url(),
       ));
       wp_enqueue_script('general');
    }
    add_action('wp_enqueue_scripts', 'enqueue_my_scripts');
  3. Изменение выпадающего списка с помощью JavaScript:

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

    document.addEventListener('DOMContentLoaded', function() {
       const checkboxes = document.querySelectorAll('.btn-check');
       const dropdown = document.getElementById('form-field-field_centre');
    
       checkboxes.forEach(checkbox => {
           checkbox.addEventListener('change', function() {
               const selectedIds = Array.from(checkboxes)
                   .filter(i => i.checked)
                   .map(i => i.id);
    
               const terms = new Set();
    
               selectedIds.forEach(id => {
                   const termArray = myVars.dropdownData[id] || [];
                   termArray.forEach(term => terms.add(term));
               });
    
               dropdown.innerHTML = '<option value="">Выберите сессию обучения</option>';
               terms.forEach(term => {
                   const option = document.createElement('option');
                   option.value = term;
                   option.innerText = term;
                   dropdown.appendChild(option);
               });
           });
       });
    });

Подход 2: Использование AJAX

Этот подход более масштабируемый и позволяет вам получать данные только тогда, когда они действительно нужны, что особенно полезно, если ваш сайт имеет большой объем данных.

  1. Создание AJAX-хука в WordPress:

    Напишите функцию, которая будет обрабатывать AJAX-запросы и возвращать данные о таксономиях. Пример:

    add_action('wp_ajax_get_terms_by_cpt', 'get_terms_by_cpt');
    add_action('wp_ajax_nopriv_get_terms_by_cpt', 'get_terms_by_cpt');
    
    function get_terms_by_cpt() {
       $cpt_id = intval($_POST['cpt_id']); // Получите ID CPT из запроса
       $terms = get_the_terms($cpt_id, 'sessions');
    
       if (!empty($terms) && !is_wp_error($terms)) {
           $responsedata = [];
           foreach ($terms as $term) {
               $responsedata[] = $term->name;
           }
           wp_send_json_success($responsedata);
       } else {
           wp_send_json_error();
       }
    }
  2. Обновление JavaScript для обработки AJAX-запросов:

    Вместо использования данных, заранее загруженных на страницу, ваш JavaScript будет делать AJAX-запросы при каждом изменении чекбокса.

    document.addEventListener('DOMContentLoaded', function() {
       const checkboxes = document.querySelectorAll('.btn-check');
       const dropdown = document.getElementById('form-field-field_centre');
    
       checkboxes.forEach(checkbox => {
           checkbox.addEventListener('change', function() {
               const selectedIds = Array.from(checkboxes)
                   .filter(i => i.checked)
                   .map(i => i.id);
    
               // Очистка выпадающего списка
               dropdown.innerHTML = '<option value="">Выберите сессию обучения</option>';
    
               // Выполнение AJAX-запроса для каждого выбранного чекбокса
               selectedIds.forEach(id => {
                   jQuery.ajax({
                       url: myVars.site_url + '/wp-admin/admin-ajax.php',
                       type: 'POST',
                       data: {
                           action: 'get_terms_by_cpt',
                           cpt_id: id
                       },
                       success: function(response) {
                           if (response.success) {
                               response.data.forEach(term => {
                                   const option = document.createElement('option');
                                   option.value = term;
                                   option.innerText = term;
                                   dropdown.appendChild(option);
                               });
                           }
                       },
                       error: function(jqXHR, textStatus, errorThrown) {
                           console.log('Ошибка на сервере:', errorThrown);
                       }
                   });
               });
           });
       });
    });

Заключение

Оба подхода имеют свои преимущества и недостатки. Если у вас небольшое количество данных и вы хотите упростить код, выберите первый подход. Для более крупных проектов и игнорирования избыточных данных рекомендуется использовать AJAX. Удачи в разработке вашего проекта!

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

Капча загружается...