4

I am using Drupal 7 and Views, I created a block and a "more link" for showing on the frontpage.

How can I move the "more link" next to the title of views block?

Mockup for the views block output

2

If you don't want the process, just result, scroll to TL;DR below!

In your view setting page, go to display of your block. In it, expand Advanced column, and on the bottom click Theme: Information. You will get screen like this:

Theme Information screen

Here you can see selection of names. You don't want to override views-view.tpl.php as it's default for all views and all displays. You want it for blocks, so views-view--block.tpl.php is a natural choice for all blocks, and views-view--test--block.tpl.php if you only want to affect view named test.

Create an empty file with selected name, click "Display output" link, copy what you see there into your file, save, and upload to your theme directory. Then, click Rescan template files - now your new template is in use and can be edited.

Problem is that block's title is not rendered in it. The part

<?php print render($title_prefix); ?>
<?php if ($title): ?>
  <?php print $title; ?>
<?php endif; ?>
<?php print render($title_suffix); ?>

is not executed as title was already rendered by block.tpl.php of your template, probably something like this:

<?php print render($title_prefix); ?>
<?php if ($title): ?>
  <h2<?php print $title_attributes; ?>><?php print $title; ?></h2>
<?php endif;?>
<?php print render($title_suffix); ?>

Similar, yes, but block.tpl.php cannot know about your $more. Trying to import it with global $more causes:

Notice: Undefined variable: more

So what do we have defined? Time to

<?php dpr(get_defined_vars()); ?>

Sadly, no luck here. So maybe we should force our theme to use view's tpl directly for blocks? In theme_preprocess_block(&$variables, $hook) temporarily add dpr($variables['block_html_id']);. Now, I see my block's id is block-views-test-block-1, so in the hook I add:

if ($variables['block_html_id'] == 'block-views-test-block-1') {
  $variables['theme_hook_suggestions'][] = 'views_view__test__block';
}

Note that - and _ are swapped between suggestion and file name. But that will not work - it will execute our tpl in a context where it has no variables. What's now? I add a bare block template, of course:

if ($variables['block_html_id'] == 'block-views-test-block-1') {
  $variables['theme_hook_suggestions'][] = 'block__raw';
}

With only one line in it:

<?php print $content ?>

Now the title is not printed using main block.tpl.php, so in your views-view--block.tpl.php you can move following section around:

But wait, $title is NOT available inside view's block template, now you can have more within the title area, but title itself is not there. So time to rollback template suggestion.

TL;DR

From your views-view--block.tpl.php remove lines that print $more. At the beginning, add:

global $block_more;
$block_more = $more;

In your main block.tpl.php, use something like:

<?php if ($title): ?>
  <h2<?php print $title_attributes; ?>><?php print $title; ?>
  <?php global $block_more; ?>
  <?php if (@$block_more): ?>
    <?php print $block_more; ?>
  <?php endif; ?>
  </h2>
<?php endif;?>

The rest is a matter of CSS.

  • If you have more than one view block on a page, this will almost certainly break. Both blocks will point to the same page on their more link (whichever was processed last.) You should not use globals to pass information around. It's not good practice. – Alfred Armstrong Oct 3 '13 at 14:07
  • @AlfredArmstrong only if all views - related templates are processed before block related ones and as far as I tested that's not the case. From your comments it seems you didn't test? I'm open to admit my mistake in testing if you will care and actually test your statement. And Drupal uses globals all the time. In a perfect world we would have unrendered view object accessible in block.tpl.php, but since we don't (we'll see how it will look like in 8), we need to get along somehow. I don't claim my answer is the best. I tried to provide as much background as possible for readers to decide. – Mołot Oct 3 '13 at 14:16
  • No, I didn't test. But did your testing include block or views caching? I'd be interested to see how that pans out. Even if it works this is not a good example for others to follow. Use drupal_static if you want globally accessible data. That's the preferred way. – Alfred Armstrong Oct 3 '13 at 15:04
  • Want another reason not to use globals? Automated testing will break. – Alfred Armstrong Oct 3 '13 at 15:06
2

You should copy the views-view.tpl.php from views module into your theme folder. If you want to do this only for a specific views, you should also rename the file like views-view--your-view.tpl.php. Then you can simply move the 'more link' part wherever you like in this template file.

UPDATE: Thanks to @Mołot's pointing about an issue that the title is rendered by the block, I've found out that there is already a discussion about that in the API page. As a workaround, you can set in the block configuration the title to <none> so that it isn't rendered by block. And in the views template replace the following part which is responsible for printing title:

<?php if ($title): ?>
  <?php print $title; ?>
<?php endif; ?> 

with this:

<?php if (empty($title)): ?>
  <?php $title = check_plain($view->get_title()); ?>
<?php else: ?>
  <?php print $title; ?>
<?php endif; ?>
  • Aren't the blocks' titles defined at a bit higher levels that views' ones? – Mołot Oct 2 '13 at 7:25
  • @Mołot if you look at the source code in the API page for views-view.tpl.php you would see that both $title and $more variables printed in the same file. – Елин Й. Oct 2 '13 at 7:30
  • So what? I just tested it and first line of views-view--test--block.tpl.php appears AFTER <h2 class="block-title">test</h2> in markup. Block's display renders title first, and then hides it so views' template doesn't. – Mołot Oct 2 '13 at 7:59
  • 1
    I didn't test it, just looked at the API page. But it seems there's already an issue about that, at least the comments at the same API page arguing about this: api.drupal.org/comment/44378#comment-44378 – Елин Й. Oct 2 '13 at 8:28
  • 1
    I did test. Process in my answer. – Mołot Oct 2 '13 at 9:06
0

One solution is to customise both the views block template (the inner part of the HTML) and the block template for the view or views in general (the outer part). So you might have a views block template as per Create template file for views block and also a block template block--views.tpl.php in your theme.

Thus you can amend your views template so it renders the title from $view->get_title() instead of the $title variable (which will be blank), and put the more link after it. At the same time you would amend the block template so it doesn't show the title at all.

But a pure CSS solution may work just as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.