From 5f4019fd8ec27d3317377f67d9b3d7903527e637 Mon Sep 17 00:00:00 2001 From: Ivan Bochkarev Date: Tue, 18 Aug 2026 07:26:20 +0600 Subject: [PATCH] docs(custom-tvs): keep the pathing plugin on 2.3 and 3.x The tutorial claimed Namespace would replace OnTVInputRenderList. Skipping the plugin still falls back to a text field on the Resource form. Fixes #201. --- en/extending-modx/custom-tvs/index.md | 70 +++++++++-------- ru/extending-modx/custom-tvs/index.md | 109 +++++++++++++------------- 2 files changed, 91 insertions(+), 88 deletions(-) diff --git a/en/extending-modx/custom-tvs/index.md b/en/extending-modx/custom-tvs/index.md index 2f4df7533..a130bd498 100644 --- a/en/extending-modx/custom-tvs/index.md +++ b/en/extending-modx/custom-tvs/index.md @@ -4,30 +4,35 @@ _old_id: "1047" _old_uri: "2.x/making-sites-with-modx/customizing-content/template-variables/adding-a-custom-tv-type-modx-2.2" --- -This tutorial is for MODX Revolution 2.2 or greater. +This tutorial is for MODX Revolution 2.2 and 3.x. ## What are Custom TV Input Types? -MODX Revolution allows you to create your own custom TV input types (similar to the textbox, radio, textarea, richtext, etc types already available) for your [Template Variables](building-sites/elements/template-variables "Template Variables"). This tutorial will show a very simple example by loading a simple Template dropdown for us in the mgr, and then in the frontend will render our Template ID wrapped in a special div. We'll call it "TemplateSelect". We'll also make this an Extra called "OurTVs", meaning that we'll have the files outside of the normal TV input renders directory, and put it in our own Extra's directory in core/components/ourtvs/. +MODX Revolution lets you add your own TV input types (beside textbox, radio, textarea, richtext, and the rest) for [Template Variables](building-sites/elements/template-variables). This example loads a Template dropdown in the Manager, then on the frontend prints the selected Template ID in a `div`. We call the type `templateselect` and keep the files in an Extra at `core/components/ourtvs/`. + +If the custom renderer is missing, MODX draws a **plain text field**. That is the fallback in `modTemplateVar::getRender()`, not a broken combo. The usual cause is skipping the pathing plugin below. ## Create a Namespace -If you haven't already, go ahead and create a Namespace called "ourtvs" with the path "{core\_path}components/ourtvs/". This will help us later on. +Create a Namespace named `ourtvs` with path `{core_path}components/ourtvs/`. + +In 3.x, MODX also scans `{namespace_path}/tv/input/` when it **lists** input types in the TV editor. That list is not the same as **rendering** the TV on a Resource. Rendering still uses the plugin events in the next step. ## Creating the Pathing Plugin -We'll need a plugin to tell MODX where our custom TV directories are. Go ahead and make a plugin called "OurTvsPlugin", and assign it to the following events: +You still need this plugin on 2.3 and on 3.x. The Namespace does not replace it for the Resource form. -- _OnTVInputRenderList_ - For rendering the actual TV input in the backend -- _OnTVOutputRenderList_ - For rendering the TV output in the frontend -- _OnTVInputPropertiesList_ - For loading any custom properties for the input render in the manager -- _OnTVOutputRenderPropertiesList_ - For loading any custom properties for the output render (front-end) of the TV -- _OnDocFormPrerender_ - For loading any custom JS/CSS for our TV +Create a plugin named `OurTvsPlugin` and attach **only** these events: -Now put in the Plugin code: +- `OnTVInputRenderList` — Manager input renderer +- `OnTVOutputRenderList` — frontend output renderer +- `OnTVInputPropertiesList` — input properties in the Manager +- `OnTVOutputRenderPropertiesList` — output properties + +Plugin code: ``` php -$corePath = $modx->getOption('core_path',null,MODX_CORE_PATH).'components/ourtvs/'; +$corePath = $modx->getOption('core_path').'components/ourtvs/'; switch ($modx->event->name) { case 'OnTVInputRenderList': $modx->event->output($corePath.'tv/input/'); @@ -41,44 +46,40 @@ switch ($modx->event->name) { case 'OnTVOutputRenderPropertiesList': $modx->event->output($corePath.'tv/properties/'); break; - case 'OnManagerPageBeforeRender': - break; } ``` -These event handlers tell MODX to check these directories for our TV files when doing all the rendering and processing. Think of it like adding library or include paths. +Those handlers add include paths. Trailing slashes matter. After you save the plugin, clear the Manager cache. -The pathing plugin will not be required in MODX 2.3; the Namespace will handle all the pathing. This is why we told you earlier to make the Namespace. :) +If you skip this plugin, the TV type may still appear in the Input Type dropdown (3.x Namespace scan), but the Resource form falls back to a text field. ## Creating the Input Controller -The input controller is what actually loads the markup for the custom TV input. Create the input controller file here: +The input controller loads the markup. Create: -> core/components/ourtvs/tv/input/templateselect.class.php +> `core/components/ourtvs/tv/input/templateselect.class.php` -And inside, you can put this code: +The file name without `.class.php` is the type key: `templateselect`. ``` php modx->getOption('core_path').'components/ourtvs/tv/input/tpl/templateselect.tpl'; } - public function process($value,array $params = array()) { + public function process($value, array $params = array()) { } } } return 'TemplateSelectInputRender'; ``` -Here we tell it where to find our smarty template for rendering the TV, as well as having a process() method to do any business logic we want to do prior to rendering the TV. +On 3.x, `modTemplateVarInputRender` is `MODX\Revolution\modTemplateVarInputRender`. The global name still works while deprecated class aliases are on (default). You can add `use MODX\Revolution\modTemplateVarInputRender;` at the top if you prefer the namespaced class. -Now you can see here we are specifying a "tpl" file for rendering our TV. Go ahead and put it here: +`getTemplate()` points at a Smarty file. Put it here: -> core/components/ourtvs/tv/input/tpl/templateselect.tpl - -And make its content: +> `core/components/ourtvs/tv/input/tpl/templateselect.tpl` ``` javascript @@ -102,24 +103,25 @@ MODx.load({ ``` -You don't have to use the ExtJS code as shown here to have a custom input type. It could even just be a straight HTML input. It's really up to you. Most importantly, your input type should have a name of `tv{$tv->id}`. +You do not have to use ExtJS. A plain HTML control is fine. The control must use the name `tv{$tv->id}`. -And that should render us a nice template dropdown in the backend: +Create a Template Variable, set Input Type to `templateselect`, assign it to a Template, then edit a Resource. You should get a Template dropdown: ![](ctv1.png) -## Creating the Output Controller +If you still see a text box: confirm the plugin is enabled on `OnTVInputRenderList`, the class file path matches the output path, and the TV type key is `templateselect`. -Okay, so now we want to make the output controller, let's create the file at: +## Creating the Output Controller -> core/components/ourtvs/tv/output/templateselect.class.php +Create: -And the content: +> `core/components/ourtvs/tv/output/templateselect.class.php` ``` php -if(!class_exists('TemplateSelectOutputRender')) { +'.$value.''; } } @@ -127,7 +129,7 @@ if(!class_exists('TemplateSelectOutputRender')) { return 'TemplateSelectOutputRender'; ``` -There we go - now when we render this in the front-end, it will display the ID of our selected Template wrapped in a div. +On the frontend this prints the selected Template ID inside a `div`. ## See Also diff --git a/ru/extending-modx/custom-tvs/index.md b/ru/extending-modx/custom-tvs/index.md index 5449c23fe..42104fc74 100644 --- a/ru/extending-modx/custom-tvs/index.md +++ b/ru/extending-modx/custom-tvs/index.md @@ -1,33 +1,38 @@ --- title: "Настраиваемые TV переменные шаблона" translation: "extending-modx/custom-tvs" -description: "Cоздание собственных пользовательских типы ввода для TV" +description: "Создание собственных типов ввода для TV" --- -Это руководство предназначено для MODX Revolution 2.2 или выше. +Это руководство для MODX Revolution 2.2 и 3.x. -## Что такое настраиваемые TV переменные шаблона? +## Что такое настраиваемые типы ввода TV? -MODX Revolution позволяет вам создавать собственные пользовательские типы ввода для [TV](getting-started/glossary#shablonnye-peremennye-ili-tv-parametry-ili-tv) (аналогичные уже доступным типам, таким как `textbox`, `radio`, `textarea`, `richtext` и т.д.) для ваших [TV](building-sites/elements/template-variables) . Это руководство покажет очень простой пример, загрузив для нас простой раскрывающийся список шаблонов в Менеджере, а затем во внешнем интерфейсе отобразит наш идентификатор шаблона, заключенный в специальный блок `
`. Назовем его `TemplateSelect`. Мы также создадим Дополнение под названием `OurTVs`, что означает, что у нас будут файлы вне обычного каталога рендеринга входных TV, и мы поместим их в наш собственный каталог Дополнения в `core/components/ourtvs/`. +MODX Revolution позволяет добавлять свои типы ввода для [TV](building-sites/elements/template-variables) рядом с `textbox`, `radio`, `textarea`, `richtext` и остальными. Этот пример показывает выпадающий список шаблонов в менеджере, а на фронтенде печатает ID выбранного шаблона в `div`. Тип называется `templateselect`. Файлы лежат в Extra по пути `core/components/ourtvs/`. -## Создаем пространство имен +Если кастомный рендерер не найден, MODX рисует **обычное текстовое поле**. Это запасной вариант в `modTemplateVar::getRender()`, а не сломанный combo. Чаще всего забыли плагин путей ниже. -Если вы еще этого не сделали, создайте пространство имен под названием `ourtvs` с путем `{core\_path}components/ourtvs/`. Это поможет нам в дальнейшем. +## Создайте пространство имён -## Создаем плагин +Создайте Namespace с именем `ourtvs` и путём `{core_path}components/ourtvs/`. -Нам понадобится плагин, чтобы сообщить MODX, где находятся наши пользовательские каталоги TV. Сделайте плагин под названием `OurTvsPlugin` и назначьте его следующим событиям: +В 3.x MODX ещё смотрит `{namespace_path}/tv/input/`, когда **перечисляет** типы ввода в редакторе TV. Список типов и **отрисовка** TV на ресурсе это разные шаги. Для отрисовки нужен плагин из следующего шага. -- _OnTVInputRenderList_ - для отображения фактического ввода TV в бэкэнде -- _OnTVOutputRenderList_ - для отображения TV-вывода в веб-интерфейсе -- _OnTVInputPropertiesList_ - Для загрузки любых настраиваемых свойств для входного рендера в Менеджере -- _OnTVOutputRenderPropertiesList_ - для загрузки любых настраиваемых свойств для выходного TV рендера (интерфейс) -- _OnDocFormPrerender_ - Для загрузки любого пользовательского JS/CSS для нашего TV +## Создайте плагин путей -Теперь введите код плагина: +Плагин нужен и в 2.3, и в 3.x. Namespace его для формы ресурса не заменяет. + +Создайте плагин `OurTvsPlugin` и повесьте **только** эти события: + +- `OnTVInputRenderList` — рендер ввода в менеджере +- `OnTVOutputRenderList` — рендер вывода на фронтенде +- `OnTVInputPropertiesList` — свойства ввода в менеджере +- `OnTVOutputRenderPropertiesList` — свойства вывода + +Код плагина: ``` php -$corePath = $modx->getOption('core_path',null,MODX_CORE_PATH).'components/ourtvs/'; +$corePath = $modx->getOption('core_path').'components/ourtvs/'; switch ($modx->event->name) { case 'OnTVInputRenderList': $modx->event->output($corePath.'tv/input/'); @@ -41,44 +46,40 @@ switch ($modx->event->name) { case 'OnTVOutputRenderPropertiesList': $modx->event->output($corePath.'tv/properties/'); break; - case 'OnManagerPageBeforeRender': - break; } ``` -Эти обработчики событий говорят MODX проверять эти каталоги на наличие наших TV файлов при выполнении всех операций рендеринга и обработки. Думайте об этом как о добавлении библиотеки или включении путей. +Обработчики добавляют пути для include. Слеш в конце пути нужен. После сохранения плагина очистите кеш менеджера. -Плагин для определения пути не потребуется в MODX 2.3. Пространство имен будет обрабатывать все пути. Вот почему мы ранее говорили вам создать пространство имен. :) +Без плагина тип может появиться в списке Input Type (в 3.x его подхватывает Namespace), но на форме ресурса останется текстовое поле. -## Создание Контроллера ввода +## Создайте контроллер ввода -Контроллер ввода - это то, что фактически загружает разметку для пользовательского входа TV. Создайте здесь файл контроллера ввода: +Контроллер ввода грузит разметку. Создайте файл: -> core/components/ourtvs/tv/input/templateselect.class.php +> `core/components/ourtvs/tv/input/templateselect.class.php` -Внутрь поместите следующий код: +Имя файла без `.class.php` это ключ типа: `templateselect`. ``` php modx->getOption('core_path').'components/ourtvs/tv/input/tpl/templateselect.tpl'; } - public function process($value,array $params = array()) { + public function process($value, array $params = array()) { } } } return 'TemplateSelectInputRender'; ``` -Здесь мы сообщаем ему, где найти наш smarty шаблон для отображения TV, а также о наличии метода `process()` для выполнения любой бизнес-логики, которую мы хотим выполнить перед отображением TV. - -Теперь вы можете видеть, что здесь мы указываем файл `tpl` для отображения нашего TV. Продолжим и добавим сюда: +В 3.x класс называется `MODX\Revolution\modTemplateVarInputRender`. Глобальное имя работает, пока включены deprecated class aliases (так по умолчанию). Можно написать `use MODX\Revolution\modTemplateVarInputRender;` в начале файла, если хотите namespaced-класс. -> core/components/ourtvs/tv/input/tpl/templateselect.tpl +`getTemplate()` указывает на Smarty-файл. Положите его сюда: -И добавим содержимое: +> `core/components/ourtvs/tv/input/tpl/templateselect.tpl` ``` javascript @@ -102,24 +103,25 @@ MODx.load({ ``` -Вам не нужно использовать код ExtJS, как показано здесь, чтобы иметь собственный тип ввода. Это может быть даже простой ввод HTML. Это действительно зависит от вас. Наиболее важно, чтобы ваш тип ввода имел имя `tv{$tv->id}`. +ExtJS не обязателен. Подойдёт обычный HTML. У контрола должно быть имя `tv{$tv->id}`. -И это должно дать нам красивый раскрывающийся список шаблонов в бэкэнде: +Создайте TV, в Input Type выберите `templateselect`, назначьте TV шаблону, откройте ресурс. Должен появиться список шаблонов: ![](ctv1.png) -## Создание Контроллера вывода +Если снова текстовое поле: плагин включён на `OnTVInputRenderList`, путь к class-файлу совпадает с `event->output`, ключ типа `templateselect`. -Итак, теперь мы хотим создать контроллер вывода, давайте создадим файл по адресу: +## Создайте контроллер вывода -> core/components/ourtvs/tv/output/templateselect.class.php +Создайте файл: -И теперь контент: +> `core/components/ourtvs/tv/output/templateselect.class.php` ``` php -if(!class_exists('TemplateSelectOutputRender')) { +'.$value.'
'; } } @@ -127,7 +129,7 @@ if(!class_exists('TemplateSelectOutputRender')) { return 'TemplateSelectOutputRender'; ``` -Итак, теперь, когда мы визуализируем это во фронтенде, он будет отображать идентификатор нашего выбранного шаблона, заключенного в `div`. +На фронтенде это выведет ID выбранного шаблона внутри `div`. ## Смотрите также @@ -135,18 +137,17 @@ return 'TemplateSelectOutputRender'; 2. [Привязки](building-sites/elements/template-variables/bindings) 3. [Привязка Чанка](building-sites/elements/template-variables/bindings/chunk-binding) 4. [Привязка Каталога](building-sites/elements/template-variables/bindings/directory-binding) -5. [EVAL Привязка](building-sites/elements/template-variables/bindings/eval-binding) -6. [Привязка файла](building-sites/elements/template-variables/bindings/file-binding) -7. [INHERIT Привязка](building-sites/elements/template-variables/bindings/inherit-binding) -8. [Привязка Ресурса](building-sites/elements/template-variables/bindings/resource-binding) -9. [SELECT Привязка](building-sites/elements/template-variables/bindings/select-binding) -10. [TV типы ввода](building-sites/elements/template-variables/input-types) -11. [TV типы вывода](building-sites/elements/template-variables/output-types) -12. [TV тип вывода - дата](building-sites/elements/template-variables/output-types/date) -13. [TV тип вывода TV - разделитель](building-sites/elements/template-variables/output-types/delimiter) -14. [TV тип вывода - HTML тег](building-sites/elements/template-variables/output-types/html) -15. [TV тип вывода - изображение](building-sites/elements/template-variables/output-types/image) -16. [TV тип вывода - ссылка](building-sites/elements/template-variables/output-types/url) -17. [Добавление произвольного TV - MODX 2.2](extending-modx/custom-tvs) -18. [Создание поля множественного выбора для страниц в вашем шаблоне](building-sites/tutorials/multiselect-related-pages) -19. [Доступ к значениям TV переменных шаблона через API](extending-modx/snippets/accessing-tvs) +5. [Привязка файла](building-sites/elements/template-variables/bindings/file-binding) +6. [INHERIT Привязка](building-sites/elements/template-variables/bindings/inherit-binding) +7. [Привязка Ресурса](building-sites/elements/template-variables/bindings/resource-binding) +8. [SELECT Привязка](building-sites/elements/template-variables/bindings/select-binding) +9. [TV типы ввода](building-sites/elements/template-variables/input-types) +10. [TV типы вывода](building-sites/elements/template-variables/output-types) +11. [TV тип вывода - дата](building-sites/elements/template-variables/output-types/date) +12. [TV тип вывода TV - разделитель](building-sites/elements/template-variables/output-types/delimiter) +13. [TV тип вывода - HTML тег](building-sites/elements/template-variables/output-types/html) +14. [TV тип вывода - изображение](building-sites/elements/template-variables/output-types/image) +15. [TV тип вывода - ссылка](building-sites/elements/template-variables/output-types/url) +16. [Добавление произвольного TV - MODX 2.2](extending-modx/custom-tvs) +17. [Создание поля множественного выбора для страниц в вашем шаблоне](building-sites/tutorials/multiselect-related-pages) +18. [Доступ к значениям TV переменных шаблона через API](extending-modx/snippets/accessing-tvs)