Theming ajaxified view/view block
Drupal 7 will no longer be supported after January 5, 2025. Learn more and find resources for Drupal 7 sites
Views module provides powerful end flexible tools to create custom template files for each element, but as it is using jQuery in few places, it is necessary to keep template structure in order, to make sure all JS and Ajax facilities will work correctly. This document describes relation between markup of Views and jQuery code which is attached to view which is using Ajax.
Required class for view container view-dom-id-{name/md5} - why and what for?
view-dom-id-{name/md5} - provided to our template with $classes variable is a main selector inside of ajax_view.js, which means that is required for views module to run ajax properly:
/**
* Javascript object for a certain view.
*/
var selector = '.view-dom-id-' + settings.view_dom_id;
this.$view = $(selector);
The reason why this class sometimes contains weird md5 hash instead of view name is explained in views_block_info() function.
block.module has a delta length limit of 32, but our deltas can unfortunately be longer because view names can be 32 and display IDs can also be 32. So for very long deltas, change to md5 hashes.
And here’s PHP code responsible for it:
foreach ($keys as $delta) {
if (strlen($delta) >= 32) {
$hash = md5($delta);
$hashes[$hash] = $delta;
$items[$hash] = $items[$delta];
unset($items[$delta]);
}
}
In conclusion: always output $classes variable to make sure ajax will init properly!
Markup for views exposed filters
When view will be successfully targeted via DOM Id, it will attempt to find exposed filters using jQuery children(); method, and standard view classes:
/**
* Add the ajax to exposed forms.
*/
this.$exposed_form = this.$view.children('.view-filters').children('form');
this.$exposed_form.once(jQuery.proxy(this.attachExposedFormAjax, this));
This forces us to keep nesting of this element in one proper way only,
.view-filters element must be a children of .view-dom-id-{name/md5} element, and the
must be rendered inside of .view-filters element. Next thing is submit button - it just needs to be placed anywhere inside of
element:
Drupal.views.ajaxView.prototype.attachExposedFormAjax = function() {
var button = $('input[type=submit], button[type=submit], input[type=image]', this.$exposed_form);
button = button[0];
this.exposedFormAjax = new Drupal.ajax($(button).attr('id'), button, this.element_settings);
};
Pagination
/**
* Attach the ajax behavior to each link.
*/
Drupal.views.ajaxView.prototype.attachPagerAjax = function() {
this.$view.find('ul.pager > li > a, th.views-field a, .attachment .views-summary a')
.each(jQuery.proxy(this.attachPagerLinkAjax, this));
};
Requirement for pagination is much simpler, because it is targeted with jQuery find(); method, so it just needs to be anywhere inside of .view-dom-id-{name/md5} wrapper, ul must have .pager class, li must be a child of ul, a must be a child of li. That’s all.
Template/markup
To make sure Ajax will work properly we don’t need to output entire view markup, this is all we need:
<div class="<?php print $classes; ?>">
<div class="views-filters">
<?php
// our exposed form must be wrapped with .views-filters class
print $exposed;
?>
</div>
<div class="view-content">
View content goes here, or anywhere.
</div>
<?php
// pager can be placed anywhere inside of main view wrapper
print $pager;
?>
</div>
And this is sample of our HTML output:
<div class="views-dom-id-{this-is-view-dom-id}">
<div class="views-filters">
<form>
<input type="submit" />
</form>
</div>
<div class="view-content">
<p>VIEWS CONTENT</p>
</div>
<ul class="pager">
<li>
<a>Page 1</a>
</li>
</ul>
</div>
Hope I didn't missed anything and it will help a little to all Themers :_)
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion