Proper way to perform AJAX request from MODx CMP (Custom Manager Page)

1k views Asked by At

I've created a CMP following this official tutorial: http://rtfm.modx.com/revolution/2.x/developing-in-modx/advanced-development/custom-manager-pages

On this CMP I have a button that I want to perform AJAX requests (on click).

What is the proper way to create php-file that will process this AJAX requests?

Either by creating php-file in /assets/components// and populating it with this code at the top:

require_once '/absolute/path/to/modx/config.core.php';
require_once MODX_CORE_PATH.'model/modx/modx.class.php';
$modx = new modX();
$modx->initialize('web');
// My code is here

or by creating another one action in System->Actions menu in manager and doing something there or in another way (by, maybe, using connectors, processors, controllers...)?

3

There are 3 answers

1
Alex Velickiy On BEST ANSWER

Well, thanks to @ride_85027 for his answer. After some discovery and googling I've come to another one solution using connector and my custom processor. Don't know which variant is "better". So here is my solution:

All my AJAX requests are sent (via POST) to connector.php file, that is placed in /assets/components/my_component_name/ with required 'action' parameter (that defines processor that will handle this request) and other custom parameters that I need. Here is the code of my connector.php:

<?php
require_once dirname(dirname(dirname(dirname(__FILE__)))).'/config.core.php';
require_once MODX_CORE_PATH.'config/'.MODX_CONFIG_KEY.'.inc.php';
require_once MODX_CONNECTORS_PATH.'index.php';

$corePath = $modx->getOption('my_component_name.core_path',null,$modx->getOption('core_path').'components/my_component_name/');
require_once $corePath.'model/my_component_name.class.php'; // My custom class
$modx->my_component_className= new my_component_className($modx);

/* handle request */
$path = $modx->getOption('processorsPath',$modx->my_component_className->config,$corePath.'processors/'); // Path to directory with my custom processors
$modx->request->handleRequest(array(
    'processors_path' => $path,
    'location' => ''
));

The action parameter is a path to processor relative to path is set in 'processors_path' in $modx->request->handleRequest. I set 'action' parameter to 'mgr/saveorder' as my custom processor file is in /core/components/my_component_name/processors/mgr/saveorder.class.php (notice that you need to omit class.php file extension from 'action' parameter.

By the way, as I discovered name of custom processor MUST be lower-case.

Here is the code of my custom processor - saveorder.class.php:

<?php
class SortArticlesSaveOrderProcessor extends modProcessor {
    public function initialize() {
    return parent::initialize();
    }
    public function process() {
        $sortOrder = json_decode($this->getProperty('order'));

        foreach($sortOrder as $order => $id) {          
            $page = $this->modx->getObject('modResource', $id);
            if (!$page->setTVValue('sort_id', $order)) {
                $this->modx->log(xPDO::LOG_LEVEL_ERROR, 'There was a problem saving sort_id in saveorder.class.php');
                return 'Ошибка.';
            }            
        }

        return 'Изменения успешно сохранены.';
    }
}
return 'SortArticlesSaveOrderProcessor';

As you see I create my class that extends modProcessor class and rewrite 'process' method. In my case it makes some changes to TVs. The AJAX request on success will get string that process method return.

For more details, please google 'modProcessor'. You will find that there are many other processors classes, provided for you to save your time.

1
camelCase On

Yes, you need to load MODx before attempting to use it outside the CMP. I do not recommend tieing each ajax file to a system->action, it's overkill. You're close with the above, here is what I often use:

if (!defined('MODX_CORE_PATH')) {
    if(strpos($_SERVER['SERVER_NAME'],'localhost') !== false){
        define('MODX_CORE_PATH', 'C:/xampp/htdocs/yoursitename/core/');
    }else{
        define('MODX_CORE_PATH', '/home2/yoursitename/public_html/core/');
    }
}
if (!defined('MODX_CONFIG_KEY')) {
    define('MODX_CONFIG_KEY', 'config');
}
require_once( MODX_CORE_PATH . 'model/modx/modx.class.php');
$modx = new modx();
$modx->initialize('mgr');

Note that the nested if/else statement is something I added to handle moving between test sites and live easily. You can simply remove it and just keep the actual /home2/yoursite..etc if wanted.

Once you initialize/load MODx in your PHP file, just use $.GET or something like it to process the request.

NOTE: If you are using custom database tables, don't forget to add your package so you can communicate with the tables! Here is a link to the addPackage request: http://rtfm.modx.com/xpdo/2.x/class-reference/xpdo/xpdo.addpackage

0
www.amitpatil.me On

I know this is old post but while looking for solution to the same problem i landed here so i am sharing my answer.

I found below tutorial really helpful

http://ridcully.dunnock.modxcloud.com/records/2014/07/08/using-custom-processors-in-modx-revolution-over-ajax-request/?quip_approved=0#quip-success-qcom