Embed a View using AJAX

11,707

Ok, so I've found the answer.

Instead of loading the View from my own callback, I'm now loading the View from the regular ajax callback.

On my page, I create the view object, and add the configuration to Drupal.settings.

$view = views_get_view('taxonomy_term');
$view->set_display('page');
$view->set_use_ajax(TRUE);
$view->set_arguments(array($tid));
$settings = array(
  'views' => array(
    'ajax_path' => url('views/ajax'),
    'ajaxViews' => array(
      array(
        'view_name' => $view->name,
        'view_display_id' => $view->current_display,
        'view_args' => check_plain(implode('/', $view->args)),
        'view_path' => check_plain($_GET['q']),
        'view_base_path' => $view->get_path(),
        'view_dom_id' => 1,
        'pager_element' => $view->pager['element'],
      ),
    ),
  ),
);
drupal_add_js($settings, 'setting');
views_add_js('ajax_view');

Then I load my js, which adds the current filter from the location.hash to the settings. And finally, loads the View.

var data = {};
// Add view settings to the data.
for (var key in Drupal.settings.views.ajaxViews[0]) {
  data[key] = Drupal.settings.views.ajaxViews[0][key];
}
// Get the params from the hash.
if (location.hash) {
  var q = decodeURIComponent(location.hash.substr(1));
  var o = {'f':function(v){return unescape(v).replace(/\+/g,' ');}};
  $.each(q.match(/^\??(.*)$/)[1].split('&'), function(i,p) {
    p = p.split('=');
    p[1] = o.f(p[1]);
    data[p[0]] = data[p[0]]?((data[p[0]] instanceof Array)?(data[p[0]].push(p[1]),data[p[0]]):[data[p[0]],p[1]]):p[1];
  });
}
$.ajax({
  url: Drupal.settings.views.ajax_path,
  type: 'GET',
  data: data,
  success: function(response) {
    var viewDiv = '.view-dom-id-' + data.view_dom_id;
    $('#content > div.limiter').html(response.display);
    // Call all callbacks.
    if (response.__callbacks) {
      $.each(response.__callbacks, function(i, callback) {
        eval(callback)(viewDiv, response);
      });
    }
  },
  error: function(xhr) {
    $('#content > div.limiter').html('<p id="artist-load-error">Error text.</p>');
    $('#block-request-0').hide();
  },
  dataType: 'json'
});

This way, the view loads through the regular flow, and everything works as expected =)

Share:
11,707
Olof Johansson
Author by

Olof Johansson

Web developer at Odd Hill in Malmö. Focused on back end development, mostly PHP and jQuery in Drupal.

Updated on June 04, 2022

Comments

  • Olof Johansson
    Olof Johansson almost 2 years

    I have a view with one argument, and a set of exposed filters. When the user filters the view, the form is submitted using Ajax, and the filters are appended to the url using location.hash.

    My goal is to filter the view upon initial page load, if the filters are present in the location.hash.

    Currently, I'm loading the view through an Ajax callback, which works perfectly fine. But the big problem is that Ajax for the view doesn't work.

    This is the callback that loads the View.

    // Load the view object.
    $view = views_get_view('taxonomy_term');
    $view->set_display('page');
    $view->set_use_ajax(TRUE);
    
    // Pass the current tid as the argument.
    $view->set_arguments(array($tid));
    // Set the current page.
    $view->set_current_page($page);
    // Set the exposed filters.
    $view->get_exposed_input();
    
    // Execute.
    return $view->execute_display();
    

    When I navigate directly to that callback, everything works. But not when I load it through Ajax.

    Any ideas?

    Update: It seems that Drupal.behaviors.ViewsAjaxView() doesn't execute for some reason. If I execute it manually, everything works.

  • Dominic
    Dominic almost 12 years
    awesome there is so little info on this on the net (no surprises there for drupal) thanks