Using ExpressionEngine Actions with AJAX

ExpressionEngine Actions are lightweight hooks in EE which allow you to register a class & method to be called on a specific URL regardless of the templates or urls which have been configured on the user’s site.

Actions are a great way for your plugin to handle AJAX requests because your EE module can register an action and then call that action from the client using jQuery or similar. However, there are a couple of caveats which you need to be aware of

In my particular case, the fact that the template engine is not loaded is a major problem because I want to return some HTML back to client – HTML which has been generated from an EE template.

Firstly, I need to make sure that the template library is loaded, and if it isn’t I need to load it manually.

class My_module {

    function __construct() {

        $this->EE =& get_instance();

        // --------------------------------------
        // Make sure the template library is loaded
        // It isn't by default when running as an action
        // --------------------------------------

        // Load EE Templates if it doesn't exist
        if ( ! class_exists('EE_Template'))
        {
	        $this->EE->TMPL =& load_class('Template', 'libraries', 'EE_');
        }
    }
}

The last thing to be aware of is that for action methods, you can’t just return your parsed template as you would in a normal module method. For example, a normal method might look like


function my_method() {

    ...

    $template  = $this->EE->functions->prep_conditionals($template, $conditionals);
    $template  = $this->EE->TMPL->parse_variables_row($template, $view_data);

    return $template;
}

However, for an action, you need to perform an extra parse step and then manually push the output to the browser.


function my_ajax_method() {

    ...

    $template  = $this->EE->functions->prep_conditionals($template, $conditionals);
    $template  = $this->EE->TMPL->parse_variables_row($template, $view_data);

    $this->EE->TMPL->parse($template);

    $this->EE->output->set_output($this->EE->TMPL->final_template);
}

Even better, if you are using JSON to return your data, you can utilise a built-in EE function to format your data. It also has the added benefit of automatically disabling the profiler.


function my_ajax_method() {

    ...

    $template  = $this->EE->functions->prep_conditionals($template, $conditionals);
    $template  = $this->EE->TMPL->parse_variables_row($template, $view_data);

    $this->EE->TMPL->parse($template);

    $data = array('html'    => $this->EE->TMPL->final_template,
                  'success' => true);

    $this->EE->output->send_ajax_response($data);
}
10
Nov 2011
POSTED BY
DISCUSSION 4 Comments
TAGS

Using Partial Views in the ExpressionEngine Control Panel (for ajax requests or similar)

If you want to use ajax to populate certain parts of your Control Panel user interface in ExpressionEngine, you will find that you have a problem if you want to use the standard MVC framework included, because EE will wrap all your views with the control panel “frame” (html/images/css etc).

For example, the following view is intended to be returned as a partial view to be called using ajax, but it will instead be wrapped by the EE control panel


public function ajax_example()
{
	// --------------------------------------
	// Load view and return it
	// --------------------------------------
	
	$data = array('some_view_data' => 'Value');

	return $this->EE->load->view('ajax_example_view', $data, TRUE);
}

To fix this, all we have to do is grab the output from our view and spit it straight out to the browser without returning it to the calling function (which is where the frame is added).


public function ajax_example()
{
	// --------------------------------------
	// Load view and echo it
	// --------------------------------------

	$data = array('some_view_data' => 'Value');

	echo $this->EE->load->view('ajax_example_view', $data, TRUE);

	exit;
}

This works, but you do lose some functionality, such as seeing the output profiler and/or template debugger. However, we can fix this by using the EE/CI output class instead to display the view.


public function ajax_example()
{
	// --------------------------------------
	// Load view and display it
	// --------------------------------------

	$data = array('some_view_data' => 'Value');

	$response = $this->EE->load->view('ajax_example_view', $data, TRUE);

	$this->EE->output->set_output($response);
	$this->EE->output->_display();

	exit;
}

This works better, but we don’t always want to see the output profiler, especially on ajax requests because the profiler output could break the layout or, if we are returning JSON for example, can destroy the output totally. So, let’s wrap this up into a helper method with some optional parameters


public function ajax_example()
{
	// --------------------------------------
	// Load view and display it
	// --------------------------------------

	$data = array('some_view_data' => 'Value');

	$this->partial_view('ajax_example_view', $data);

}

private function partial_view($view_name, $data, $show_profiler = null) {

	$response = $this->EE->load->view($view_name, $data, TRUE);

	if(isset($show_profiler)) {
		$this->EE->output->enable_profiler($show_profiler);
	}

	$this->EE->output->set_output($response);
	this->EE->output->_display();

	exit;
}
08
Nov 2011
POSTED BY
DISCUSSION 2 Comments
TAGS