Add-on Creation and Modification - MODX Community Forums <![CDATA[ [Solved] Custom LocalGrid - enableRowBody Not Being Applied]]>
I have made a custom resource class and have used the loadCustomCssJs function in my create controller to add a customised version of the create resource form which allows me to add the fields in my custom resource classes related tables.

The resource represents an event. I have added a grid to allow users to add multiple pricing for various vendors selling tickets.

My code for the extended LocalGrid I am using is:

rdBoxOffice.grid.Prices = function(config){
    config = config || {};

    this.exp = new Ext.ux.grid.RowExpander({
        tpl : new Ext.Template('test')

        id: 'rdboxoffice-grid-prices'
        ,url: rdBoxOffice.config.connectorUrl
        ,baseParams: { action: 'mgr/prices/getList' }
        ,pluralText: 'Prices'
        ,singleText: 'Price'
        ,viewConfig: {
          deferEmptyText: false

          ,enableRowBody: true
        ,tbar: [
                title: _('listing_create_price'),
                text: _('listing_create_price'),
                handler: this.addPrice
        ,fields: [
        ,remoteSort: false
        ,plugins: [this.exp]
        ,columns: [this.exp,{
            header: _('listing_prices_vendor')
            ,dataIndex: 'fullname'
            ,sortable: true
            ,width: 100
            header: _('listing_prices_regular')
            ,dataIndex: 'regular'
            ,sortable: true
            ,width: 100
            header: _('listing_prices_vip')
            ,dataIndex: 'vip'
            ,sortable: true
            ,width: 100
            header: _('listing_prices_student')
            ,dataIndex: 'student'
            ,width: 100

In my create resource form I have added it as so:

To initially load some default pricing into the grid I have used the following code in the setup function for the resource panel - it works fine:

var pricesStore = Ext.getCmp('rdboxoffice-grid-prices').getStore();
record = new pricesStore.recordType({vendor_id:sitevendorid,fullname:'Website',regular:0,vip:0,student:0});

The panel is displayed and the default pricing loaded with the expand button showing that the row is contracted but when I look at the markup produced in the web developer console, there is no second row in the markup and therefore when clicking the expand button, I get an error because the row can't be found to add the compiled template.

Besides explicitly setting the enableRowBody config to true, I also note that the MODX derived grids all have enableRowBody set to true in their default configs but the grid is behaving as it's set to false. To confirm this I edited the ext-all.js file and modified the only mention of enableRowBody in there to output a string if enableRowBody is false. That string is output in my grid so somehow that config option is getting changed but I've no idea how.

I was wondering whether the way I was adding the record to the store was the problem but adding the data using loadData does display the data in the grid with the expand button but once again, no second row in the table holding the columns.

I modified the ext-all.js file to set the enableRowBody configuration to true and that makes my grid work as expected with the second row added and my rowexpander works. That seems to suggest some kind of problem with the config being passed back to Ext.grid.Grid.

I'm open to all suggestions as to how to take this further.]]> Sun, 06 Jan 2019 08:13:36 +0000
<![CDATA[New Extra: JoliTypo for MODX – Please give Feedback before first Release]]> i needed a smart and configurable Typography-Fixer for MODX. I think JolyTypo has a good configuration, so i try to put it in an extra. Please test it and give me feedback. Thank you!

Code:]]> Wed, 02 Jan 2019 11:19:09 +0000
<![CDATA[Maps integration and leaflet.js]]>
Does anyone have any interest in maps and / or experience using leaflet.js?

Wordpress have a plug in for this, which is basically a port of it, which then helps with markers, showing where you are on your map, etc.
]]> Thu, 27 Dec 2018 06:09:39 +0000
<![CDATA[How do i add a custom button on tinymce editor?]]>

On button click event popup will open where i will be showing list of items from 3rd part api, I googled a lot and found few forum posts as well but either they are not identical to what i am searching or too old, which does not resemble with latest modx revo version.

Does anyone have some clue about it ?]]> Thu, 04 Oct 2018 01:15:24 +0000
<![CDATA[OnDocFormSave and a simple internal function - what's going wrong here ...]]>
at the moment I don't understand modx, because the following minimal code example
did not work. On pressing the Save-Button in a Resource the system hangs:

$PlugName = "TestPlugIn";

// ****** Internal Functions ******

function MyInternalFn($id) {

// ****** Handle MODX Events ******

switch ($modx->event->name) {
    // ****** OnDocFormRender with $mode $resource $id *********************************************************************************************
    case 'OnDocFormRender':
        $modx->log(MODX_LOG_LEVEL_INFO, "[$PlugName -> ".$modx->event->name."] ID: ($id)   Mode:($mode)");
    // ****** OnBeforeDocFormSave with $mode $resource $id  ****************************************************************************************
    case 'OnBeforeDocFormSave':
        $modx->log(MODX_LOG_LEVEL_INFO, "[$PlugName -> ".$modx->event->name."] ID: ($id)   Mode:($mode)");
    // ****** OnDocFormSave with $mode $resource $id ***********************************************************************************************
    case 'OnDocFormSave':
        $modx->log(MODX_LOG_LEVEL_INFO, "[$PlugName -> ".$modx->event->name."] ID: ($id)   Mode:($mode)");
    // ****** OnBeforeEmptyTrash with $ids *********************************************************************************************************
    case 'OnBeforeEmptyTrash':
        $modx->log(MODX_LOG_LEVEL_INFO, "[$PlugName -> ".$modx->event->name."] Anzahl zu löschender IDs: (".count($ids).")");
    default: break;

There are to ways, the system doesn't hang anymore:
1) Remove the function MyInternalFn or
2) Remove the system event 'OnDocFormSave' for this PlugIn
Both variants I don't understand, because the code
should work ...

]]> Mon, 27 Aug 2018 04:26:48 +0000
<![CDATA[Help reloading a Manager Page in OnDocFormSave using PHP]]>
I know how to do it in JavaScript, but in this use-case, I need to do it with PHP.

The problem seems to be that the action goes to the connector, rather than straight to the browser. I've tried stuff that works in JS (e.g., sending ?a=resource/update&id=12), but it doesn't work.

Has anyone figured out a way?]]> Sun, 26 Aug 2018 07:54:46 +0000
<![CDATA[How to create Resources (documents) from the front end (with a form)?]]> Fri, 17 Aug 2018 05:26:02 +0000 <![CDATA[ModLDAP: LDAP User Integration for REVO]]>
The package can be found on Github:
Pre Release 2.4.1-alpha: (Tested on my 2.4.2 MODX installation)

Thanks for testing and feedback
@zaenal]]> Mon, 26 Mar 2018 05:41:50 +0000
<![CDATA[MyComponent - project config not updating on bootstrap]]>
1. I have created my own project and edited the config file in /core/components/mycomponent/_build/config/
2. Bootstrap the new project. All looks good.
3. Hack around with the code generated in /assets/mycomponents/newproject/. I'm not using mgr to edit anything at this stage.

I'm happy so far. Chunks, snippets etc etc are all in place and when I build my package they're all there (and install as I'd expect).

4. I then decide to use install.options to allow an API key to be added during installation, and add the form HTML to user.input.php
5. Specify a (default) resolver in project config, bootstrap again. Add my code to the resolver that's created.

However, when I build my project now, the resolver isn't added to the transport package (I only worked this out after my resolver code wasn't being run, took a while!). The instructions say not to mess with the config file that's placed in /assets/mycomponents/newproject/_build/config/ so I haven't but I noticed that it hadn't been updated. In the name of experimentation, I renamed it to something else, ran boostrap again and it re-generated. A build of the project now includes the resolvers I later added.

I'm happy enough that I can get round it but if I've misunderstood part of the process, pointers would be grateful.

Thank you, BobRay for what is an incredible amount of work and a huge timesaver. I'd been put off creating packages for MODX for so long, I wish I'd looked at this years ago.


]]> Mon, 05 Mar 2018 09:31:21 +0000
<![CDATA[googleSitemap not working with multiple contexts]]>
The resource is sitting in the web context and needs to reference the es and en contexts. The web context is the default context and the german version of the website.

Anyone have any tips?

I am running Revo 2.2.4 and Babel 2.2.5]]> Mon, 19 Feb 2018 07:47:02 +0000
<![CDATA[Doodle tutorial part 3 - menu built problem]]> http://localhost/modxtest/manager/?a=2 instead of http://localhost/modxtest/manager/?a=index&namespace=doodles (if you corrent the path manualy then it works fine)

I checked the menu how is made and is not as it should be.

On dev version Action is set to "index", on installed one is set to 2
Also namespace is wrong. On dev version is "doodles" but on installed one is "core"

My "menu" code inside build.transport.php looks like:
$modx->log(modX::LOG_LEVEL_INFO,'Packaging in menu...');
$menu = include $sources['data'].'';
if (empty($menu)) $modx->log(modX::LOG_LEVEL_ERROR,'Could not package in menu.');
$vehicle= $builder->createVehicle($menu,array (
    xPDOTransport::PRESERVE_KEYS => true,
    xPDOTransport::UPDATE_OBJECT => true,
    xPDOTransport::UNIQUE_KEY => 'text',
    xPDOTransport::RELATED_OBJECTS => true,
    xPDOTransport::RELATED_OBJECT_ATTRIBUTES => array (
        'Action' => array (
            xPDOTransport::PRESERVE_KEYS => false,
            xPDOTransport::UPDATE_OBJECT => true,
            xPDOTransport::UNIQUE_KEY => array ('namespace','controller'),

And my is:

$action= $modx->newObject('modAction');
    'id' => 1,
    'namespace' => 'doodles',
    'parent' => 0,
    'controller' => 'index',
    'haslayout' => true,
    'lang_topics' => 'doodles:default',
    'assets' => '',
$menu= $modx->newObject('modMenu');
    'text' => 'doodles',
    'parent' => 'components',
    'description' => 'doodles.desc',
    'icon' => 'images/icons/plugin.gif',
    'menuindex' => 0,
    'params' => '',
    'handler' => '',
return $menu;

I know that in the past for action a numeric id value was used instead of namespaces like now. I asked about it on slack and markh replied with:

If you want to use the new style in that build, drop the $action and set the namespace + action as string on the menu

:) I don't have a clue what he ment.

I'm looking through various extras on github to find how to define that in different way but I didn't had any luck yet.

Thanx for any info]]> Sun, 04 Feb 2018 04:05:17 +0000
<![CDATA[ExtJS Grid ComboBox Default value]]>
Ext.util.Format.comboRenderer = function(combo){
    return function(value){
        var record = combo.findRecord(combo.valueField, value);
        return record ? record.get(combo.displayField) : combo.emptyText;

Ebents.combo.organizer = function(config){
    config = config || {};
        url: Ebents.config.connectorUrl,
        baseParams: { action: 'mgr/organizers/getComboBoxList', combo: true },
        hiddenName: 'organizer',
        name: 'organizer',
        displayField: 'name',
        valueField: 'id',
        fields: ['id','name'],
        loadingText:  'Loading...',
        emptyText: 'Select...'

And the grid config (unrelated code omitted:
Ebents.grid.Events = function(config) {
    config = config || {};
        url: Ebents.config.connectorUrl
        ,baseParams: { action: 'mgr/events/getlist'} 
        ,fields: ['id','name','description','organizer','venue','start','end','status']
        ,loadMask: true
        ,save_action: 'mgr/events/updateFromGrid'
        ,autosave: true
        ,paging: true
        ,remoteSort: false
        ,anchor: '97%'
        ,columns: [{
                header: _('ebents.event_organizer')
                ,dataIndex: 'organizer'
                ,sortable: true
                ,width: 100
                ,editor: { xtype: 'ebents-combo-organizer'}
                ,renderer: Ext.util.Format.comboRenderer(Ebents.combo.organizer)

With this setup I get
Uncaught TypeError: combo.findRecord is not a function(anonymous function) @ events.grid.js:3Ext.grid.GridView.Ext.extend.doRender @ ext-all.js:21

According to the docs, findRecord is an available function for 3.4. Not sure why it would be undefined here unlessI'm calling it wrong. I'd rather not have to rewrite the whole thing with a bunch a vars like the example. I just want to display the value back from getlist in the column. I saw some posts about setting the value in this thread,61332.msg348573.html, but that didn't work either.]]> Sun, 07 Jan 2018 09:28:50 +0000
<![CDATA[Dropbox uploader error : Error: Cannot extract token! (form action=/login)]]> Linux server

UHG,... I've been getting an error on my dropbox downloader (installed from package management)
when I try to download a file. Its been working for a year but decided to go haywire on me.

The Error is:
Error: Cannot extract token! (form action=/login)

With some research I've read that has upped their interface restrictions (security) on their getdropbox page.

I've tried reinstalling the add-on with no effect. Also found fixes for the wordpress and jumla versions of the dropbox uploader but the php code doesn't correspond (not surprising). Does anyone have a fix for this?

I guess I could use the original php and make into a chunk and call it but I was hoping that there was a better solution.

Any clue as to fixing this would be greatly appreciated.

Thanks, RL]]> Wed, 27 Dec 2017 11:37:14 +0000
<![CDATA[EmailResource Updated to 1.1.2-rc2]]>

PLEASE, PLEASE specify the version of MODX you are using . . . PLEASE!
MODX info for everyone:]]> Sun, 05 Nov 2017 09:54:38 +0000
<![CDATA[Very basic custom snippet returning nothing - snippet needs to return external assets from a 3rd party integration]]>
I need to integrate a 3rd party booking system search bar and have been provided with the code to do this, which contains 2 php calls which load further JS. I can test run this locally fine in standard php via MAMP but can't get anything loading in MODX when using snippets to call the provided php.

The following is what I’ve been provided with (I changed the domain name here).

This loads a form and fetches a JS file:
echo file_get_contents("");

This just loads a bunch of external JS assets:
echo file_get_contents("");

Firstly I changed 'echo' to 'return' and then just added the 2 code blocks verbatim into a couple of new snippets respectively, however, when I call these snippets I'm getting zero return. I've tried calling them cached/uncached but with no joy. Both snippets do actually work as I added a simple text string which renders fine.

Can anyone advise on how I can get a return from these snippets with the code provided?

For the record I have tried this whole shebang with only the form and external JS assets, i.e. without the need for any php call/snippets, plus loading the JS more performantly. But that is throwing console errors and various other malarkey so I’m looking at the original suggestion.

Here's the build setup:
MODX Revolution: 2.5.7-pl (traditional)
PHP Version: 5.6.30
MySQL Client API version: mysqlnd 5.0.11-dev (from phpinfo file)
Database client version: libmysql - 5.1.73 (from phpMyAdmin)
Server version: 5.6.35 - MySQL Community Server (GPL) (from phpMyAdmin)
Protocol version: 10

Thanks in advance.]]> Fri, 22 Sep 2017 03:24:38 +0000
<![CDATA[Login snippet and multiple contexts]]>
Based on what I found in the Login snippet code (1.5.2) there are 3 different proprieties that relate directly to contexts: contexts, login_context and add_contexts. By adding these proprieties to my snippet call, I would assume that they would allow my users to be logged into multiple contexts after login, but it doesn’t look like it is working for me.

to test this my code includes a reference to the logged in user [[+modx.user.username]] - a link to another context withing the site and finally the snippet call. After login, my reference user name appears, so I know I have successfully logged into the main site context. However after I follow the link to another context, my user reference [[+modx.user.username]] displays anonymous (not logged in).\

Here is my snippet call: [[!Login? &loginTpl=`FormLogin` &errTpl=`FormLoginError` &loginResourceId=`1` &logoutResourceId=`1` &contexts=`contextb`]].

Any help would be appreciated.
]]> Tue, 19 Sep 2017 09:31:33 +0000
<![CDATA[Static Resources and Media Sources]]>
if($resource->get('class_key') == 'modStaticResource'){
    $resource->set('template', 0); /*optional. i didn't need these to have templates and i assume loading one is slower than not.
                                     plus if a text or html static resource has a template the file will be inserted into the content area like a page*/
    $path = $resource->get('content');
    if(count(explode('/', $path)) > 2) return;
    $msid = $modx->getOption('default_media_source', null, 'default');
    $ms = $modx->getObject('modMediaSource', $msid);
    $props = $ms->getProperties();
    $path = $props['baseUrl']['value'].explode('assets/usermedia', $path)[1];
    $resource->set('content', $path);


This was written to fit my particular situation but should be easy to modify to fit any other particular situation. It requires that a default media source be set in the context, user group or user settings. In my case all file names were being prepended with assets/usermedia, e.g. assets/usermediaSomePDF.pdf, so I isolated the file name by exploding on that string and then appended it to the baseUrl value from the media source. The correct paths do begin with assets/usermedia but include an additional subdirectory so before doing anything I check the number of forward slashes in the path and if there's more than one I assume it's already correct and return without doing anything.

If I understood where it was getting the "assets/usermedia" string it might be possible to make this generic but my investigation has thus far not turned that information up.

Hope this is helpful to somebody.

Dave]]> Fri, 15 Sep 2017 03:45:28 +0000
<![CDATA[Need help with Gallery and Slimbox plugin]]>
My gallery itself is looking good, but I can't get the Slimbox to work and I tried several things:

1. [[Gallery? &album=`Hairpower` &plugin=`slimbox` &slimboxRenderJsOnStartup=`1` &thumbWidth=`250` &thumbHeight=`250` &ZoomCrop=`1` $linkToImage=`1`]]

--> when adding this plugin to the properties, my gallery is a mess. It's placing all the images underneath eacht other in stead of placing them nicely in rows. When clicking on the picture, you get redirected to an non-existing web page so you arrive at a modx base template.
(see for yourself:

What am I missing here? Probably it's something stupid, but I have been breaking my head several hours now and I just can't find it. Anyone?

(I'm using MODX Revolution 2.5.7-pl)
]]> Fri, 15 Sep 2017 12:45:21 +0000
<![CDATA[mycomponent: addusers.resolver.php - problem creating user groups and setting super user role]]>
I would like to create a package using mycomponent. So I installed MODX and mycomponent. Basically I know how to create packages with mycomponent.

So far the package I'm working on does only contain a modified addusers.resolver.php (no chunks, resources etc.). The code that I added to this file works fine if run as snippet. But if the code is run in the addusers.resolver.php while package installation, the installation gets stuck (no package installation success message). But the code is executed successfully because the user groups are created and the super user is added to the newly created user groups and got super user role.

Am I doing something wrong? Is the addusers.resolver.php file not the place to create user groups? Or is it very uncommon to do that in a package installation routine?

Here is the installation console output ('sitelogin' is the package name):
Console running...
Attempting to install package with signature: sitelogin-1.0
Package preparing to install.
Grabbing package workspace...
PHP notice: Undefined offset: 2
Workspace environment initiated, now installing package...

The php notice does appear on installation of every package that I created with mycomponent (may refer to a php version?).

This is the addusers.resolver.php:
 * Resolver for flightschool extra
 * Copyright 2017 by Björn Kaiser
 * Created on 01-20-2017
 * @package flightschool
 * @subpackage build

/* @var $object xPDOObject */
/* @var $modx modX */

/* @var array $options */

$new_user_groups = array(
    'Member Group 1',
    'Member Group 2);

if ($object->xpdo) {
    $modx =& $object->xpdo;
    switch ($options[xPDOTransport::PACKAGE_ACTION]) {
        case xPDOTransport::ACTION_INSTALL:
            foreach ($new_user_groups as $new_user_group)
                // create new user group
                $response = $modx->runProcessor('security/group/create', array('name' => $new_user_group));
                // add super user to the new user group
                if (!$response->isError())
                    $group = $response->getObject();
                    $modx->runProcessor('security/group/adduser', array('user_group' => $group['id'], 'member' => 1));

                    // change super user role to 'Super User' role
                    $user_group = $modx->getObject('modUserGroup', array('name' => $new_user_group));
                    $user_group_id = $user_group->get('id');

                    $user_group_member = $modx->getObject('modUserGroupMember', array('user_group' => $user_group_id, 'member' => 1, 'role' => 1));
                    $user_group_member->set('role', 2);
        case xPDOTransport::ACTION_UPGRADE:
            /* [[+code]] */

        case xPDOTransport::ACTION_UNINSTALL:
            // remove created user group
            foreach ($new_user_groups as $new_user_group)
                $user_group = $modx->getObject('modUserGroup', array('name' => $new_user_group));
                $response = $modx->runProcessor('security/group/remove', array('id' => $user_group->get('id')));

return true;

Best regards,
Björn]]> Wed, 05 Jul 2017 03:04:53 +0000
<![CDATA[Check if template variable is filled with a value]]> I want to create a snippet where I check if a template variable is filled with a value (image) or not (Template Variable is an image). If tried almost the whole afternoon, but it makes me bezerk...

The code:
// Retrieve TV
$tv_value = $modx->getTemplateVarOutput('image_1');

// Check if TV is filled
if(!empty($tv_value)) echo '$tv_value has a value';

The strange thing is that always get back that the TV in the document I’m putting this snippet on has is filled with a value. That’s not the case as TV’s of some pages are filled and other not. I’m not a php expert, so any help is welcome.

Thanks in advance!]]> Mon, 22 May 2017 10:16:12 +0000