Returning page attributes with AJAX
PermalinkFirst off, in my .js I have the following, which is taking a preset value from a selected checkbox (the value being a page ID) and sending it to my ajax php script;
$(document).ready(function() { $('.product-filter').change(function(){ $.ajax({ url: 'filter-ajax.php?filter='+$(this).val(), success: function(data){ $('#filterResponse').html(data); } }); }); });
I've checked that this is working by just echoing back the value from the .php file to the page like so;
<?php $filter = $_GET['filter']; echo '<p>'.$filter.'</p>'; ?>
And it does the job, the page ID set from the selected checkbox gets printed to the page.
But what I need is for that page ID to be worked through some more php and have that parsed code returned, as in;
<?php $filter = $_GET['filter']; $d = PAGE::getByID($filter); $page = $d->getCollectionName(); echo '<p>'.$page.'</p>'; $attr_set = AttributeSet::getByHandle('technical'); $attr_keys = $attr_set->getAttributeKeys(); foreach($attr_keys as $ak) { echo '<p>'.$ak->akName.'</p>'; echo '<p>'.$d->getAttribute($ak->akHandle).'</p>'; }; ?>
So basically, when the checkbox is selected, I need this to send back to the body of the page the page name for the selected option, and the page attributes for that page (the code there for those is working fine, I just need to be able to switch which page it pulls them from dynamically).
I'm also pretty sure I'm doing something more fundamentally wrong, as
<?php $filter = $_GET['filter']; $d = PAGE::getByID($filter); $page = $d->getCollectionName(); echo '<p>'.$page.'</p>'; ?>
doesn't work either, so I think nothing there's getting parsed?
Been googling and searching through tutorials and FAQs for a good few hours now, and not any closer to making this work. I've seen JSON mentioned a few places, but it doesn't seem like it'll do what I need, and I'm just about getting my head around this part at the moment as it is.

Nope, and I'd have been really surprised if it did, as the code works when put directly into the page with a page id put in by hand.
The problem is getting it parsed and sent back. I'm 98% sure, anyway.
you are echoing your result in your PHP file but that file is not attached to your page in any way, it is just an external tool called by ajax.
From that php file you need to send the result back to ajax that will then show it on the page throughout normal jquery dom manipulation.
from your PHP, you could put your return values (page name...) in an array
$ret = array('name' => $d->getCollectionName);
then after your array is ready you do
We are encoding the array to json for ajax to consume.
Now you need to alter your original ajax call to use that return data
$.ajax({ url: 'filter-ajax.php?filter='+$(this).val(), dataType: "json" }).done(function(data, textStatus, jqXHR){ var name = data.name; $('#filterResponse').html(name); }).fail(function(jqXHR, textStatus, errorThrown){ if (textStatus === 'parsererror') { alert('Requested JSON parse failed.'); } else if (textStatus === 'timeout') { alert('Time out error.'); } else if (textStatus === 'abort') { alert('Ajax request aborted.'); } else if (jqXHR.status === 0) { alert('Not connected.\n Verify Network.');
Notice I am using .done() instead of success which is deprecated
My php file is now;
and my .js is;
$(document).ready(function(){ $('.product-filter').change(function(){ $.ajax({ url: 'filter-ajax.php?filter='+$(this).val(), dataType: "json" }).done(function(data, textStatus, jqXHR){ var name = data.name; $('#filterResponse').html(name); }).fail(function(jqXHR, textStatus, errorThrown){ if (textStatus === 'parsererror') { alert('Requested JSON parse failed.'); } else if (textStatus === 'timeout') { alert('Time out error.'); } else if (textStatus === 'abort') { alert('Ajax request aborted.');
And this is returning the Internal Server Error [500].
$d = Page::getByID($filter);
notice the capital P in Page.
In what context are you using this code? In a theme's page type? In a block?
I'm currently trying to work it into the a page template in the theme. It seemed the simplest way to see if I could get it working without throwing a lot of other potential problems into the mix.
If it's relevant, filter-ajax.php is in the site's root as it wouldn't seem to work anywhere else.
How might that look for a call from the page template rather than a block?
I like the legacy tools since all I have to do is upload a single file and call it ;)
You can name your routes however you want, but this (untested) example would make your new AJAX url: '/task/' + $(this).val()
// return a JSON encoded pageID name (route parameter id) Route::register('/task/{id}', function($id) { $id = intval($id); if ($id < 1) { $ret = array('error' => 'Invalid Page ID'); } else { $d = Page::getByID($id); if (is_object($d)) { $ret = array('name' => $d->getCollectionName); } else { $ret = array('error' => 'Failed to retrieve page'); } } $json = Core::make('helper/json'); echo $json->encode($ret);
Here's how to fake some tools:
// fake legacy tools file functionality Route::register('/tools/{name}', function($name) { $name = trim($name); if ($name) { $file = 'application/tools/'. $name. '.php'; if (is_readable($file)) { include $file; } } }); // or, just a single one Route::register('/tools/get-vars', function { include 'application/tools/get-vars.php'; });