Существует очень клевый jQuery плагин Select2 — он позволяет существенно расширить возможности выбора данных.

В нем есть отличные возможности по подгрузке данных через AJAX.

И мне не сразу хватило документации, чтобы научиться правильно и оптимально встраивать его в WordPress.

Потому запишу сюда простой пример с шорткодом и AJAX с особенностями WordPress.

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

 

Тут мы сразу разберем ряд особенностей такой задачи:

1. Простой возврат большого HTML куса через механизм шорткода

2. Особенности работы AJAX в WordPress

3. Особенности настройки Select2

Заготовка плагина

Создаем php файл, помещаем его в папку с плагинами и добавляем ему шапку по кодексу:

<?php

/*
 Plugin Name: Test Select2 & AJAX
 Plugin URI: http://casepress.org
 Description: Это учебный плагин для понимания механизмов Select2 & AJAX в WordPress
 Author: CasePress
 Author URI: http://casepress.org
 Version: 20141112
*/

Шорткод и форма

Добавляем шорткод и заготовку для формы

function select_posts_in_page_callback($attr){
 ob_start(); 
 ?>
 <div>
  <form>
   <input id="my_posts" type="text" name="my_posts" />
   <br />
   <input type="submit" />
  </form>
  <script type="text/javascript">
   jQuery(document).ready(function($) {
    // тут будет код инициализации Select2
   });
  </script>
 </div>
 <?php
 $html = ob_get_contents();
 ob_get_clean();
 return $html;
}
add_shortcode('select_posts_in_page', 'select_posts_in_page_callback');

 

Добавляем Select2 и AJAX запрос постов

function select_posts_in_page_callback($attr){
 ob_start();
 ?>
 <div>
 <form>
 <input id="my_posts" type="text" name="my_posts" />
 <br />
 <input type="submit" />
 </form>
 <script type="text/javascript">
 jQuery(document).ready(function($) {

 //Создаем поле Select2 + AJAX для выбора участников в деле
 $("#my_posts").select2({
 placeholder: "Добавить посты...",
 formatInputTooShort: function (input, min) { return "Пожалуйста, введите " + (min - input.length) + " или более символов"; },
 minimumInputLength: 1,
 formatSearching: function () { return "Поиск..."; },
 formatNoMatches: function () { return "Ничего не найдено"; },
 width: '100%',
 multiple: true,
 ajax: {
 url: "<?php echo admin_url('admin-ajax.php?action=query_my_posts_from_wp_ajax') ?>",
 dataType: 'json',
 quietMillis: 100,
 data: function (term, page) { // page is the one-based page number tracked by Select2
 return {
 posts_per_page: 10, // page size
 paged: page, // page number
 s: term //search term
 };
 },
 results: function (data, page) {

 var more = (page * 10) < data.total; // whether or not there are more results available

 // notice we return the value of more so Select2 knows if more results can be loaded
 return {
 results: data,
 more: more
 };
 }
 },

 formatResult: function(item){ return "<div>" + item.title + "</div>" }, // omitted for brevity, see the source of this page
 formatSelection: function(item){ return item.title; }, // omitted for brevity, see the source of this page
 dropdownCssClass: "bigdrop", // apply css that makes the dropdown taller
 escapeMarkup: function (m) { return m; } // we do not want to escape markup since we are displaying html in results
 });
 
 });
 </script>
 </div>
 <?php
 $html = ob_get_contents();
 ob_get_clean();
 
 return $html;
}
add_shortcode('select_posts_in_page', 'select_posts_in_page_callback');


 // Получаем список групп через AJAX запрос
function get_my_posts_callback() {
 
 $items = array(); // контейнер для данных, который мы получим и отправим
 $data = get_posts(array(
 'fields' => 'ids',
 's' => $_REQUEST['s'],
 'paged' => $_REQUEST['paged'],
 'posts_per_page' => $_REQUEST['posts_per_page'],
 'post_type' => 'cases'
 ));
 
 foreach ($data as $post_id){
 $items[] = array(
 'id' => $post_id,
 'title' => get_the_title($post_id)
 );
 }
 
 //отправляем массив данных как JSON строку http://codex.wordpress.org/Function_Reference/wp_send_json
 wp_send_json($items);
}
add_action( 'wp_ajax_query_my_posts_from_wp_ajax', 'get_my_posts_callback' );

Добавляем функцию сохранения

function save_data_from_shortcode(){

 if(empty($_REQUEST['my_posts'])) {
 return;
 } else {
 $my_posts = explode( ',', $_REQUEST['my_posts']);
 }
 
 
 global $post;
 
 delete_post_meta($post->ID, 'my_posts');

 foreach($my_posts as $post_id){
 //exit(var_dump($post->ID . 'sdfsdf' . $post_id));

 add_post_meta($post->ID, 'my_posts', $post_id);
 }
 
}
add_action('wp', 'save_data_from_shortcode');

Добавляем метод подстановки уже выбранных постов

Все хорошо, но при загрузке страницы мы не увидим те данные, что уже сохранены в мету.

Для этого нужно вставить условный срипт добавления уже существующих данных.

И в итоге получаем вот такой код: