6

I'm trying to build a view with a different number of items for the first page (2 items) than the others (3 items). How can I build it to avoid skipping items ?
I made tests using hook_views_pre_build() but the result isn't conclusive as the second page will miss one item (item C):

Here is my current code:

function MYMODULE_views_pre_build(&$view) {
  if ($view->name == 'my_view' && empty($_GET['page']) {
    //The view normally has 3 items per page, put 2 for the first page.
    $view->items_per_page = 2;
  }
}

And here is the result I obtain:

First page:

  • item A
  • item B

Second page:

  • item D
  • item E
  • item F

As you can see, item C is missing because setting the number of items per page to 3 imply that the first page also has 3 items.

Is there another way to get this working ?

4
  • Have you tried to override the number of items through Views UI? Or is the view completely hand coded? Jun 3, 2013 at 4:40
  • What do you mean by "override the number of items through Views UI" ? How can I do this for only the first page ?
    – tostinni
    Jun 3, 2013 at 20:58
  • In Views UI at the top of any settings popup (incl. pagers) you get a dropdown select that has 2 options: 1) All displays 2) This page (override). If you click on the later the settings that you set here will apply only to this page and not the rest. Jun 4, 2013 at 1:10
  • Sure but there I can't specify which page I'll override, it's for the whole display. (when I mean page it's not display, it's for page nº1 of my pager).
    – tostinni
    Jun 4, 2013 at 3:48

3 Answers 3

2

This is how I got it working, use two hooks. Assuming we have a view called my_view and the display is page_1.

Pre-build: Set the items per page to 10 for the first page.

Pre-render: Add an additional CSS class to the view.

/**
 * Implements hook_views_pre_build().
 */
function my_module_views_pre_build(ViewExecutable $view) {
  if ($view->id() === 'my_view' && $view->current_display === 'page_1') {
    // Page is zero indexed: first page is NULL or 0.
    if (!$view->getRequest()->query->get('page')) {
      // Default is 9, we set it to 10.
      $view->setItemsPerPage(10);
    }
    else {
      // Set the offset on subsequent pages, because we have one more on the first page.
      $view->setOffset(1);
    }
  }
}

/**
 * Implements hook_views_pre_render().
 */
function my_module_views_pre_render(ViewExecutable $view) {
  if ($view->id() === 'my_view' && $view->current_display === 'page_1' && !$view->getCurrentPage()) {
    // Add CSS class for first page.
    $view->display_handler->setOption(
      'css_class',
      $view->display_handler->getOption('css_class') . ' is-first-page'
    );

    // To attach a library, use:
    // $view->element['#attached']['library'][] = 'my_module/view-first-page';
  }
}
1

Assuming Drupal 7:

What you can do is have two different displays for your view.

This requires the first display to be a 'block' and the second to be a 'page'.

The first display you will change the pager to "Display a specified number of items" and set the number of items to show to 2.

Enable the "more link".

On the second display you change the number of items to 3 and set the offset to 2.

Currently there is no way to have a view's page display have a more link to another display or view.

This only works from a block display to a page display, tho you could have your block display in a panels page.

2
  • Note 1) He can use footer in page display to provide equivalent of a "more" link. Note 2) It's hard to make two views share an alias, like example.org/myview/1 for first one and example.org/myview/2 and more for the second. And it's not quite easy to make first page of a view show under 2 in url and pager.
    – Mołot
    Jun 3, 2013 at 8:30
  • Yes it's for D7, if I create more than one display I would have an inconsistent pager as the second display will start on page 1 when it really is page 2. Thanks for the suggestion.
    – tostinni
    Jun 3, 2013 at 21:00
0

You could use the offset property to do something like this:

function MYMODULE_views_pre_build(&$view) {
  if ($view->name == 'my_view') {
    // The view normally has 3 items per page, put 2 for the first page.
    if (!isset($_GET['page']) || $_GET['page'] <= 0) {
      $view->items_per_page = 2;
    }
    else {
      $view->offset = -1;
    }
  }
}

Not really the cleanest way to do this since you'll need to change those hardcoded numbers if you change the number of items in the view... But it's fast and it works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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