В панели администратора Joomla встречаются поля, которые нужно заполнить данными из других компонентов: указать материал, пункт меню, контакт, товар и т.д. Обычно такие поля оформляются в виде выпадающего списка select option, могут оформляться в виде input type="text" с datalist, но есть и удобные поля, показывающие список искомых сущностей, с фильтрацией, поиском, пагинацией и т.д.  Все мы видели эти поля в действии при выборе материала в пункте меню типа "Материалы - Материал", "Контакты - Контакт", или при создании алиаса (псевдонима) пункта меню - "Системные - Псевдоним". Однако напомним себе как они выглядят. Модальное окно выбора материала. На видео - утро, компьютер ещё не проснулся и локальный сервер чуть тупит ))  А это модальное окно выбора контакта. Давайте пристально посмотрим на эти поля - что именно они позволяют сделать. Мы где-то глубоко внутри понимаем, что основная работа этого поля - получить id выбираемой сущности и поместить это id в текстовое поле. Но на экране мы видим нечто другое - вместо цифры мы видим название материала или контакта. Это приятно и удобно. Не нужно вспоминать название материала с id 1452704. Также, на видео отчётливо видно, что если в поле уже есть значение - появляется кнопка "очистить". Она сбрасывает значение поля и позволяет снова нажать на кнопку "выбрать". В  некоторых случаях у нас есть возможность создать выбранный тип сущности - материал, контакт и т.д. прямо в процессе создания пункта меню. Эта кнопка работает с учётом ACL - разделения прав доступа в Joomla.  Представьте, Вы собираете сайт и создаёте страницу "Контакты". Если у Вас не куча филиалов с разветвлённой структурой, то это как правило обычный материал Joomla в категории "Без категории". И в нём уже все контакты. В бородатые времена нужно было сначала создать материал, а потом уже идти в пункты меню и делать на него ссылку. Сейчас так можно не делать. И если в поле уже есть значение, то в некоторых же случаях есть возможность редактировать выбранную сущность (материал, пункт меню и т.д.) прямо в процессе создания пункта меню. Итак, с помощью поля выбора в модальном окне мы можем: выбрать создать редактировать очистить Это то, что перед глазами. Но в недрах Joomla есть ещё любопытный параметр urlCheckin, который позволяет отправлять выбранное значение на указанный в поле url. Стоит заметить, что этот функционал в Joomla постепенно развивался с довольно давних пор. Однако, отдельный универсальный тип поля, который можно использовать для своих нужд появился только в Joomla 5. Его нет даже в Joomla 4. Раньше этот конструктор назывался JForm . Я буду предполагать, что не все мои читатели имеют в руках такой инструмент разработки как IDE - среду разработки - а-ля PHP Storm или VS Code, поэтому постараюсь давать дополнительные ориентиры для навигации по кодовой базе.  В Joomla логика разделена от представления (собственно вывода HTML), поэтому исследовать мы будем одновременно в нескольких местах. Логика - это класс Form. В Joomla 5 файлы классов Form находятся в libraries/src/Form. Эти файлы мы исследуем для того, чтобы понять саму логику, что и как происходит с данными и как с этим работать. Если кратко, то конструктор Form получает XML с описанием полей. считывает данные (тип поля, кастомный класс поля из атрибута addfieldprefix, если есть и т.д.), загружает с помощью FormHelper нужный класс поля. Если у поля есть некие правила фильтрации выводимых данных - используется класс FormRule  - вспомните поля Joomla типа filelist, где можно указать параметры фильтрации и выбрать, например, только php или только css файлы. Честно скажу, что на данный момент сам до конца не знаю всех тонкостей работы, статья выросла сугубо из практического опыта. Поэтому не буду погружаться здесь слишком глубоко, дабы случайно не наврать 😎. Файлы классов полей Joomla Form находятся в libraries/src/Form/Field. Их, мягко говоря, много. Это строительный материал админки, а порой и фронта. В файлах классов описаны свойства класса, такие как $type , $layout и другие необходимые для работы. У большинства полей есть методы getInput() - собственно вызов представления (HTML-вывода) поля, getLayoutData() - предобработка данных для поля перед отдачей их на рендер, getLabel() - работа с заголовком поля и т.д.  Мы помним, что классы полей наследуют родительский класс FormField.  В файле класса libraries/src/Form/FormField.php описаны возможные атрибуты поля, которые можно использовать при описании в XML с кратким описанием того что это и зачем. У классов-детей (наследников) есть возможность работать с методами родительского класса и при необходимости переопределять его.  У каждого класса поля есть представление. В классическом MVC представление работает с выводом данных сразу, однако в Joomla есть прослойка - Layout, которая позволяет делать переопределения макетов - одна из важнейших фич этого движка. Ожидаемо лейауты ядра находятся в папке layouts. В них передаётся массив $displayData со всеми данными, полученными из метода  getLayoutData() .  Какой именно макет вывода использовать  указываем в свойстве класса $layout. Такой тип записи встречается довольно часто. В Joomla layout - это разделенный точками путь к файлу макета от папки layouts в корне сайта. То есть запись $layout = 'joomla.form.field.email' означает, что при рендере поля будет использоваться макет layouts/joomla/form/field/email.php.  Аналогично, в этом примере будет использоваться макет layouts/joomla/html/image.php. Некоторые макеты можно переопределять в папке html шаблонов сайта и админки. Подробнее об этом статья Создание шаблонов сайта в Joomla 4+. Соответственно, если мы хотим посмотреть какие именно данные приходят в конце-концов в макет и как они отображаются - идём в файл макета и смотрим. Теперь вернемся к основной задаче статьи. Упомяну здесь статью Создание плагина кнопки редактора в Joomla 4, которая в целом описывает ту же задачу, но в контексте плагина кнопки редактора и вставки данных в редактируемую область.  Эта статья описывает много деталей, поэтому далее я буду предполагать, что с ней Вы уже познакомились. В этой статье я буду больше говорить об отличиях и деталях, характерных именно для поля Form. Нам важны примеры для изучения: основной класс поля - libraries/src/Form/Field/ModalSelectField.php выбор материала Joomla - admin istrator/components/com_content/src/Field/Modal/ArticleField.php выбор типа меню - administrator/components/com_menus/src/Field/MenutypeField.php выбор пункта меню - administrator/components/com_menus/src/Field/MenutypeField.php макет вывода - layouts/joomla/form/field/modal-select.php Поле с выбором контакта из com_contacts на момент написания статьи ещё не переделано на универсальное и просто лежит в administrator/components/com_contact/src/Field/Modal/ContactField.php. Оно наследует напрямую FormField, а не ModalSelectField. Алгоритм действий для добавления своего поля следующий: создаём в xml-файле или программным методом с помощью \SimpleXMLElement XML форму с нашим полем. Если мы работаем "на лету". то плагином на событие onContentPrepareForm добавляем XML формы в нужную форму (проверяем $form->getName() перед этим) Создаем класс поля. Если нужно - создаём собственный вывод (layout) поля. Это мы оставим за пределами данной статьи. И оно работает. Самым важным в этом коде является атрибут addfieldprefix, который означает namespace  Вашего класса поля. Имя класса образуется из addfieldprefix + "\" + type + "Field". В данном случае класс поля будет Joomla\Plugin\Wtproductbuilder\Providerjoomshopping\Field\ProductlistField. Для того, чтобы всё происходящее в PHP было понятно - нужно для начала посмотреть макет вывода поля. Он находится в файле layouts/joomla/form/field/modal-select.php. На самом деле выводится 2 поля input - одно видимое, другое невидимое. В видимое поле в виде placeholder заносится название выбранного материала, контакта или товара - параметр $valueTitle. А во второе - его id - $value. Если у нас еще ничего не выбрано - в поле должна быт фраза в духе "выберите материал" или "выберите товар". Это языковая константа, которую мы помещаем в атрибут hint в XML поля или же в методе setup класса поля. Все доступные для макета вывода параметры (а значит те, что можно использовать программно или в XML-файле): Класс поля, как Вы уже догадались, находится у меня в плагине. Путь к нему plugins/wtproductbuilder/providerjoomshopping/src/Field/ProductlistField.php. Я взял за основу поле выбора материалов и переделал его под свои нужды - выбор товара из интернет-магазина JoomShopping. Мы расширяем родительский класс ModalSelectField своим классом. В мои задачи входит только выбор товара, редактирование и создание - нет, поэтому в тексте статьи речь идёт только о выборе товара. Класс небольшой, приведу его целиком и прокомментирую. Отдельно вынес метод getValueTitle(), который показывает название выбранной сущности (название товара, заголовок материала и т.д.) в тех случаях, когда они уже выбраны и сохранены. То есть, мы зашли отредактировать пункт меню, поле не трогаем, но хотим видеть заголовок материала / название товара человекопонятное, а не просто id. Этот метод показывает нужный заголовок. В некоторых полях, где требуется более сложный функционал - мультиязычные ассоциации и прочее - в классе поля встречаются и другие методы, которые переопределяют базовые методы класса FormField:  getLayoutData()  - метод предобработки данных перед собственно рендером поля getRenderer() - дополнительные параметры для рендера и так далее. В нашем случае такой необходимости нет, поэтому их не используем. При нажатии на кнопку "выбрать" открывается модальное Bootstrap окно, в котором в <iframe> открывается список товаров. По клику на название товара или картинку Javascript получит id и название товара для нашего поля. Но, чтобы получить сам HTML этого списка - мы должны его где-то реализовать. То есть такой вывод и функционал должен либо поддерживать компонент и тогда мы будем обращаться по URL компонента. Либо через com_ajax мы обращаемся к плагину и получаем HTML оттуда. Так и поступим.  В моём плагине метод onAjaxProviderjoomshopping() возвращает вёрстку списка товаров. Там мы циклом проходим массив с ними, берем картинку, название и выводим. Код в целом объёмный, поэтому опубликую самые важные фрагменты. Первое - добавляем в <iframe> наш javascript, который будет слушать клики по картинкам и названиям товаров. Оформляем его в виде медиа-ассета к плагину и подключаем через Web Asset Manager.  Для любопытных статьи: Как правильно подключать JavaScript и CSS в Joomla 4 Использование WebAssetsManager Joomla 4 (Joomla 5) и добавление собственных пресетов с помощью плагина Второе. Код тега ссылки должен содержать data-атрибуты с нужными нам данными. Теперь приступим к работе с JavaScript. В процессе написания статьи выяснились нюансы, которые позволяют говорить о старом и новом способе работы.  Мы помним, что в процессе работы мы подключили следующие js-скрипты media/system/js/fields/modal-fields.min.js - этот файл подключался в классе поля выбора материала. Однако, сейчас можно говорить. что архаизм и устаревший метод работы. Этот файл уже не нужен. Мы его закомментировали в нашем PHP классе. media/plg_wtproductbuilder_providerjoomshopping/js/providerjoomshopping.modal.js - наш собственный js-файл. Начнём с собственного javascript. Здесь мы по классу select-link получаем все селекторы и вешаем на них слушателя события клика.  Если с id и title всё интуитивно понятно, то с объектом data и postMessage тем, кто привык работать с Joomla, может быть не всё очевидно.  Раньше в Joomla 2.5, 3.x и даже в 4.x использовался следующий подход: в макете вывода поля мы инлайн скриптом вешали на window функцию-обработчик, а из <iframe> вызывали её как window.parent[functionName]. Посмотрите на этот код В таком виде имя функции было указано в атрибуте data-function  каждой ссылки списка материалов / контактов / пунктов меню. А саму функцию помещали инлайн, иногда уникализируя её имя дополнительным id. Например, "jSelectArticle_".$this->id.  Функция jSelectArticle() или ей подобные (у нас была бы jSelectProduct()) являются обёрткой для штатной функции processModalSelect() из файла modal-fields.min.js. Она в свою очередь вызывает функцию processModalParent() и после выполнения закрывает модальное окно. Этой функции для работы требовалось указать кучу параметров: тип сущности (материал. контакт и т.д.), префикс поля (который на практике оказался id HTML-селектора поля), собственно id и title  - нужные нам параметры и т.д.  В одной функции было собрано всё на все случаи жизни. Именно там данные помещались в наше поле. Однако, сейчас, в Joomla 5 этот файл уже не нужен. Если мы используем стандартный макет вывода поля, то в нём подключается ассет modal-content-select-field, работающий по-новому.  Сейчас Joomla 5 фронтенд переходит на использование JavaScript postMessages. Поскольку не все старые расширения ещё готовы перейти на новые рельсы внедрён флаг JoomlaExpectingPostMessage, который позволяет отличать устаревшие методы вызова событий. К описываемому способу работы он имеет косвенное отношение, но может быть кому-то полезен. Данный флаг будет удалён после полного перехода на postMessages. Итак, нам теперь не нужны лишние атрибуты ссылок с именем вызываемых функций. Вместо этого мы используем механизм postMessage. Для этого в объекте data нам нужно указать параметр messageType равным joomla:content-select. Почему? С точки зрения JavaScript работа в Joomla происходит следующим образом: клик по ссылке и получение атрибутов ссылки отправка сообщения в родительское окно window.parent.postMessage(data) в родительском окне подключён файл media/system/js/fields/modal-content-select-field.js, в котором есть слушатель события message. Он проверяет тип сообщения и если это joomla:content-select, то значения помещаются в нужные поля и модальное окно закрывается Я, в процессе изучения кода ядра и поиске решения естественно набрёл на функции jSelectArticle() и подобные. Потом столкнулся с postMessage  и решил сделать свой messageType, дав ему длинное уникальное имя. Чтобы оно заработало - к нему написал свою обработку, вызвав (как оказалось устаревшую) функцию processModalSelect(). И столкнулся с тем, что модальное окно ни в какую не хотело закрываться, хотя данные в поля вставлялись корректно. Дальнейшие поиски привели сначала к правильному типу события, а потом и к удалению ненужных скриптов и упрощению кода в целом. Конечно, такое модальное окно и выбор сущностей в нём - это довольно частный случай, но, надеюсь, он будет кому-то полезным.  Если уважаемые читатели обнаружат где-то неточности, опечатки, неверные тезисы - пишите, подправим.  форум русской поддержки Joomla. интернет-портал Joomla-сообщества. https://vc.ru/s/1146097-joomla - Сообщество Joomla на VC. Чат сообщества «Joomla! по-русски». Joomla для профессионалов, разработчики Joomla. Новости о Joomla! и веб-разработке по-русски. Вакансии и предложения работы по Joomla: фуллтайм, частичная занятость и разовые подработки. Размещение вакансий здесь. Англоязычный чат сообщества. Новости Joomla! по-английски  Joomla-разработчик (WebTolk). Муж. Отец 3 детей.