[Solved] Custom TV - Cannot declare class modTemplateVarInputRenderText & Bug

I’m currently trying to create a custom tv type and have followed the article at Custom Template Variables - Extending MODX | MODX Documentation but not creating the paths plugin as I am working in MODX 2.8.3-pl. I have an input and output class as detailed in the article and they appear to be correct.

The tv type is available in the tv creation form dropdown so it seems the namespace is working to locate it, but when I choose it and associate it with a template, documents using that template produce the error in the title.

I have seen a couple of posts online about this but no fixes. Has anyone seen this and can they suggest where I should be looking for the problem?

Below is my input class code for reference. I have ruled out an issue with the template loading by having it only output HTML.

<?php
if(!class_exists('ImageEditorInputRender')) {
    class ImageEditorInputRender extends modTemplateVarInputRender {
        public function getTemplate() {
            return $this->modx->getOption('core_path').'components/mynamespace/tv/input/tpl/imageeditor.tpl';
        }
    }
}
return 'ImageEditorInputRender';

Strange, the error is related to modTemplateVarInputRenderText while your custom TV extends modTemplateVarInputRender.
Seems it’s not related to your custom TV.
Can you show us how you setup the tv’s Input Options?

There are no input options beyond the default - maybe that’s the problem? It’s a simple image field to which I am adding a button to allow for some user editing of the image. It seems like (though I haven’t yet confirmed) that when there is an issue with a custom tv, it defaults to the text class mentioned in the error and that’s where the problem lies. In the posts I have found relating to this error, people have mentioned a reinstall of a custom tv package fixed the issue so it seems like MODx isn’t completely registering mine. I did try with the plugin too just to see if that would resolve things but unsurprisingly it didn’t.

I’m going to look more closely at the code for the standard image tv and see if that yields anything around the input options.

Have you try to add a plugin first?

$corePath = $modx->getOption('core_path',null,MODX_CORE_PATH).'components/ourtvs/';
switch ($modx->event->name) {
    case 'OnTVInputRenderList':
        $modx->event->output($corePath.'your/tvs/dir/');
        break;

to add option to Input Options?

Try to learn from Migx.

What’s happening is that there is an issue with one of the TVs and, when a problem arises rendering a given TV (usually a non-core one), the fallback is to render a text field; the additional condition is that a text type TV has already been loaded beforehand. See this PR which, although it is for 3.x, the same applies to 2.x. Since the text TV class has already been loaded and used, a fatal error occurs because you cannot redeclare a class in PHP. In the end, this points to a problem with a TV renderer, but also exposes a small bug in the core that should be handling that issue gracefully.

I figured it was something like this. Between you all I am realising that I should have extended my input class from the built in image one and that I also need to specify the same input options as the image tv has. It would be useful for others if the possible necessity for the input options was mentioned in the article I referred to in my original post.

I’ll report back what I learn from implementing the input options.

Still struggling with this. If the only code I add is the input class and the output class, and they just produce standard html, why would my tv have this issue? What else could be going wrong? How would I go about debugging this?

You still need a plugin.
If you have no input properties and no output renderer, then at least run it on the event OnTVInputRenderList:

<?php
$corePath = $modx->getOption('core_path',null, MODX_CORE_PATH) . 'components/mynamespace/';
switch ($modx->event->name) {
    case 'OnTVInputRenderList':
        $modx->event->output($corePath . 'tv/input/');
        break;
}

Did you create the namespace (via the gear menu, upper right) for the TV? If so, can you post all code you’re using to create the TV and the paths to each file? (No need to re-post the input render class if you’ve not changed what you posted above.)

Thanks , the article I referred to above specifically says that the namespace makes the paths plugin moot. but I’ll give it a try.

The namespace is set up and functional - use it on a wide variety of functions within the website already. The tv name appearing in the tv type dropdown also suggests the tv is being found.

I have an input and output class just returning basic html from the getTemplate function. What I don’t understand is what produces the tv interface on a resource with access to it because the input class posted above obviously isn’t displaying even if I substitute the template returned with basic HTML - it seems that’s where things are going pear shaped. I’ve looked at a few other custom TV’s and each seems to have it’s own way of doing things. Am I missing a class to actually render the interface on a resource with access to the TV?

The only other code I have deployed on the test site is the output class which I guess is where the tv gets output on the frontend:

if(!class_exists('ImageEditorInputRender')) {
    class ImageEditorInputRender extends modTemplateVarInputRender {
        public function getTemplate() {
           // return $this->modx->getOption('core_path').'components/mynamespace/tv/input/tpl/imageeditor.tpl';
           return '<h2>Here is my input</h2>';
        }
    }
}
return 'ImageEditorInputRender';

Can you post your tpl code?

to rule out a template issue I am just returning a simple h2 tag.

I have added the plugin, ensured the paths in it are correct, each class returns a simple html tag, the inputoptions and inputproperties files return a simple html string - still no change, Other custom tvs I have installed from developers obviously way smarter than me are functioning fine.

On the basis of other posts I have seen mentioning this error, I wrapped the MODX text input class in a class_exists wrapper - bizarrely still seeing the error even after manually nuking the cache.

Ok, so here’s a working setup for you to replicate:

The basic structure I used looks like this —

core/components/imageeditor
┗ tv
┃ ┣ input
┃ ┃ ┗ imageeditor.class.php
┃ ┣ inputproperties
┃ ┃ ┗ imageeditor.php
┃ ┗ tpl
┃ ┃ ┗ input
┃ ┃ ┃ ┗ imageeditor.input.tpl

The plugin, which is in fact necessary (the docs are wrong on this AFAIK), contains

<?php
$corePath = MODX_CORE_PATH . 'components/imageeditor/';
switch ($modx->event->name) {
    case 'OnTVInputRenderList':
        $modx->event->output($corePath . 'tv/input/');
        break;
    case 'OnTVInputPropertiesList':
        $modx->event->output($corePath . 'tv/inputproperties/');
        break;
}
return;

imageeditor.class.php contains

<?php

if (!class_exists('ImageEditorInputRender')) {
    class ImageEditorInputRender extends modTemplateVarInputRender {
        public function getTemplate() {
            return $this->modx->getOption('core_path') . 'components/imageeditor/tv/tpl/input/imageeditor.input.tpl';
        }
    }
}
return 'ImageEditorInputRender';

imageeditor.php contains (just returns an empty string instead of options for demonstration)

<?php

return '';

and, imageeditor.input.tpl contains (again, just test output)

<p>This TV id: tv{$tv->id}</p>

Without seeing exactly all you’ve done, it’s hard to know where it’s going wrong; I can only tell you that this example works.

Thanks this is REALLY helpful, I’ll post back when I identify the breaking difference in my code.

So I replaced all my code with yours including the plugin and deployed it - still the same error. The only difference that I can see is your code is the directory structure change but I don’t think that should matter. I manually cleared the cache again, nothing.

I then decided maybe it would be worth a punt to resave the TV and I did. I set the TV to another type, then back to mine and saved and voila, it now works.

I’ve no idea why resaving the tv would make a difference but maybe this is useful to someone else with the same issue.

Thanks to all who contributed to the thread!

So I replaced all my code with yours including the plugin and deployed it - still the same error. The only difference that I can see is your code is the directory structure change but I don’t think that should matter. I manually cleared the cache again, nothing.

I then decided maybe it would be worth a punt to resave the TV and I did. I set the TV to another type, then back to mine and saved and voila, it now works.

I’ve no idea why resaving the tv would make a difference but maybe this is useful to someone else with the same issue.

Thanks to all who contributed to the thread!