Jump to main content Jump to doc navigation

This tutorial is for MODX Revolution 2.2 or greater.

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. 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/.

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.

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:

  • 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

Now put in the Plugin code:

$corePath = $modx->getOption('core_path',null,MODX_CORE_PATH).'components/ourtvs/';
switch ($modx->event->name) {
    case 'OnTVInputRenderList':
        $modx->event->output($corePath.'tv/input/');
        break;
    case 'OnTVOutputRenderList':
        $modx->event->output($corePath.'tv/output/');
        break;
    case 'OnTVInputPropertiesList':
        $modx->event->output($corePath.'tv/inputoptions/');
        break;
    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.

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. :)

Creating the Input Controller

The input controller is what actually loads the markup for the custom TV input. Create the input controller file here:

core/components/ourtvs/tv/input/templateselect.class.php

And inside, you can put this code:

<?php
if(!class_exists('TemplateSelectInputRender')) {
    class TemplateSelectInputRender extends modTemplateVarInputRender {
        public function getTemplate() {
            return $this->modx->getOption('core_path').'components/ourtvs/tv/input/tpl/templateselect.tpl';
        }
        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.

Now you can see here we are specifying a "tpl" file for rendering our TV. Go ahead and put it here:

core/components/ourtvs/tv/input/tpl/templateselect.tpl

And make its content:

<select id="tv{$tv->id}" name="tv{$tv->id}" class="combobox"></select>
<script type="text/javascript">
// <![CDATA[
{literal}
MODx.load({
{/literal}
    xtype: 'modx-combo-template'
    ,name: 'tv{$tv->id}'
    ,hiddenName: 'tv{$tv->id}'
    ,transform: 'tv{$tv->id}'
    ,id: 'tv{$tv->id}'
    ,width: 300
    ,value: '{$tv->value}'
{literal}
    ,listeners: { 'select': { fn:MODx.fireResourceFormChange, scope:this}}
});
{/literal}
// ]]>
</script>

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}.

And that should render us a nice template dropdown in the backend:

Creating the Output Controller

Okay, so now we want to make the output controller, let's create the file at:

core/components/ourtvs/tv/output/templateselect.class.php

And the content:

if(!class_exists('TemplateSelectOutputRender')) {
    class TemplateSelectOutputRender extends modTemplateVarOutputRender {
        public function process($value,array $params = array()) {
            return '<div class="template">'.$value.'</div>';
        }
    }
}
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.

See Also

  1. Creating a Template Variable
  2. Bindings
    1. CHUNK Binding
    2. DIRECTORY Binding
    3. FILE Binding
    4. INHERIT Binding
    5. RESOURCE Binding
    6. SELECT Binding
  3. Template Variable Input Types
  4. Template Variable Output Types
    1. Date TV Output Type
    2. Delimiter TV Output Type
    3. HTML Tag TV Output Type
    4. Image TV Output Type
    5. URL TV Output Type
  5. Adding a Custom TV Type - MODX 2.2
  6. Creating a multi-select box for related pages in your template
  7. Accessing Template Variable Values via the API