Use AJAX with modxAPI
From MODx Wiki
You want to create AJAX stuff in modx? Find below 2 possible solutions to do that
Contents |
Introduction
The first one called "Full MODx solution" which offers a full access to MODx API
The second one called "Lightweight solution"
The recipe Three layers of code
To use modx API in AJAX calls we need to create 3 files: 2 php files + 1 javascript file
1 controller program (snippet or standalone php program) for backend stuff
1 view snippet for frontend stuff (forms who sends data to backend program)
1 javascript file to handle the AJAX connection (we use mootools to achieve this)
The Full MODx solution
In this example we would like to display ditto results.
Ingredients
Javascript file
window.addEvent('load', function() { var element = $('container'); var mySlider = new Fx.Slide(element, {duration: 500,transition: Fx.Transitions.backOut}); $('demoForm').addEvent('submit', function(e) { mySlider.hide() new Event(e).stop(); //asuming that the backend snippet is located in document 22 new Ajax("[~22~]",{ //get all the variable/value pairs from the form postBody:$('demoForm').toQueryString(), onComplete:showResponse, update:element }).request(); }); function showResponse(request){ mySlider.hide() mySlider.toggle() //toggle the slider up and down. } })
frontend snippet
<?php $modx->regClientStartupScript("manager/media/script/mootools/mootools.js"); $modx->regClientStartupScript("[~21~]");//asuming that my javascript file for do the trick is located in the document 21 switch($action){ //each case will have a mirror in the backend snippet //in this example we will call a simple ditto snippet //for this example i use a container div for update the content via ajax //the most important line of code of this form is the hidden input, because this line has the action for the backend case "dittoAjax": //asuming that the backend snippet is located in document 22 $output =' <form method="post" action="[~22~]" id="demoForm"> <input id="action" name="action" type="hidden" value="dittoAjax" /> <button type="submit">run ditto</button> </form><br/><br/><div id="container"></div>'; echo $output; break; } ?>
backend snippet
<?php $action=$modx->db->escape($_POST['action']); switch($action){ case "dittoAjax": $params['startID'] = 0; $params['display'] = 5; $params['randomize'] = 1; $html = $modx->runSnippet('Ditto', $params); echo $html."<br/></div>";//this is for adjusting some error with the animation in safari break; } ?>
How to cook the files
We need to make three documents in the modx manager, one for the javascript file, one for the frontend snippet and one for the backend snippet. Both the backend and the javascript documents must not have a template assigned, just set that to blank <- this is really important! Also make sure to set the content type for the javascript document to "text/javascript"! In the backend documents' content field just enter [[nameOfBackendSnippet]], the javascript code is pasted directly into the javascript document.
The frontend snippet will be placed in any document you want, and you need to call it [!anyName? &action=`dittoAjax`!] to make appear the form that will call the backend part via the javascript mootools function for handling the ajax calls.
If you want more functionality in your ajax framework, you only need to add more cases in both snippets.
If anyone uses this technique or wants to do so (or knows how to perfect it...) please visit me at dospuntocero.cl and drop me a line ;)
Lightweight solution
We will take as example the display of informations (member card) of a "member" from a member list
Ingredients
Javascript file : assets/snippets/memberList/js/memberList.js
// Frontend Snippet folder location var _base = 'assets/snippets/memberList/'; window.addEvent('domready', function(){ lis = $$("#memberlist li"); for(i=0;i<lis.length;i++){ li = lis[i]; li.addEvent('click', function(e) { e = new Event(e).stop(); var url = _base + 'memberCard.php'; var pars = Object.toQueryString({ q: url, id: this.id }); new Ajax('index-ajax.php', {postBody: pars, update: $('card') }).request(); }); } });
frontend snippet : assets/snippets/memberList/memberList.php.tpl
<?php $modx->regClientStartupScript("manager/media/script/mootools/mootools.js"); $modx->regClientStartupScript("assets/snippets/memberList/js/memberList.js"); return '<h3>Members list :</h3> <div id="card"></div> <ul id="memberlist"> <li id="23"><a href="#">Pierre Ponce</a></li> <li id="37"><a href="#">Jean Bonneau</a></li> <li id="41"><a href="#">Melusine Enfaillite</a></li> <li id="48"><a href="#">Paul Ochon</a></li> </ul>'; ?>
backend php program : assets/snippets/memberList/memberCard.php
The memberCard program do a search in the database and display the information card of the member
<?php require_once(MODX_MANAGER_PATH . '/includes/protect.inc.php'); // Setup the MODx API define('MODX_API_MODE', true); // initiate a new document parser include_once(MODX_MANAGER_PATH.'/includes/document.parser.class.inc.php'); $modx = new DocumentParser; $modx->db->connect(); // provide the MODx DBAPI $modx->getSettings(); // provide the $modx->documentMap and user settings $id = $modx->db->escape($_POST['id']); $fields = "country, fullname, email, phone, comment"; $from = $modx->db->config['table_prefix']."memberlist"; $where = "id = $id"; $card = $modx->db->getRow($modx->db->select($fields, $from, $where)); echo "<span> Country: {$card['country']} Full name: {$card['fullname']} Email: {$card['email']} Phone: {$card['phone']} Comment: {$card['comment']} </span>"; ?>
How to cook the files
We need one document in the modx manager for the frontend snippet and the two files in the snippet folder, one for the javascript file, one for the backend program. As in the "Full MODx solution", the javascript file could be managed as a MODx document too (see above).
The frontend snippet will be placed in any document you want, and you need to call it [!MemberList!] to make appear the member list. Click on any name will call the backend part via the javascript mootools function for handling the ajax calls.
If you want more functionality in your ajax framework, you only need to add more cases in both snippet and backend program.
Keep in mind that in this "lightweight solution" you have a part of the MODx core, not all the MODx API available.
If anyone uses this technique or wants (or knows how to perfect it...) please visit me at modx.wangba.fr and dropme a line ;)
Differences and conclusions
In the "full MODx API solution" the ajax request is setting up with :
new Ajax("[~22~]",{
In the "lightweight" solution:
new Ajax('index-ajax.php', {postBody: pars, update: $('card') }).request();});
In the first solution you set up your ajax request with index.php and you call the MODx parser method to build the answer. In the second solution you set your ajax request with index-ajax.php and you call only the initialisation of database Variables. So you need to initiate a new document parser to use the global $modx and populate the $modx->documentMap array with:
// Setup the MODx API define('MODX_API_MODE', true); // initiate a new document parser include_once(MODX_MANAGER_PATH.'/includes/document.parser.class.inc.php'); $modx = new DocumentParser; $modx->db->connect(); // provide the MODx DBAPI $modx->getSettings(); // provide the $modx->documentMap and user settings
The choice of the solution depends of your needs and of your MODx programming knowledge. "Full MODx API solution" offer all the MODx facilities and a great level of reuse. But running entire MODx application to service an ajax script could be overkill and heavy if you need a simple and fast answer to your ajax request.
"Lightweight solution" is faster but offer a "limited" MODx API and needs to deep into the code.
