2

Page manager and theme suggestions

I have two types of layout

custom_2col_brick
custom_1col_landing

and I need to render the page according to the selected layout. basically, I needed two page template for each layout. something like the following:

page__custom_2col_brick.html.twig
page__custom_1col_landing.html.twig

Is there a way to do this?

In Drupal 7 I could do it as follows, but panels_get_current_page_display is not working in Drupal 8

/**
 * Implements hook_preprocess_page().
 *
 * @see page.tpl.php
 */

function THEME_preprocess_page(&$variables) {

    if (module_exists('ctools') && module_exists('page_manager')) {
        $display = panels_get_current_page_display();
        $layout = (isset($display->layout)) ? $display->layout : false;

        /* layout e.g column_one_fluid, column_three_fluid etc. */
        $fluid   =  $layout ? preg_match("/\s*.+_fluid$/", $layout) : false;

        /* layout e.g column_one_landing, column_three_landing_fluid etc. */
        $landing =  $layout ? preg_match("/\s*.+_landing$|\s*.+_landing_fluid$/", $layout) : false;

        $variables['page_fluid'] = ($fluid) ? true : false;
        $variables['page_landing'] = ($landing) ? true : false;

        if($fluid) {
             $variables['theme_hook_suggestions'][] = 'page__fluid';
        }
        if($landing) {
            $variables['theme_hook_suggestions'][] = 'page__landing';
        }

    }
1

If you don't already have one create a yourtheme.layouts.yml file in your theme folder. There you will define the regions, preview icons, and labels.

custom_2col_brick:
  label: Two Column Brick
  category: My Custom Layouts
  template: layouts/custom_2col_brick
  icon: layouts/custom_2col_brick.png
  regions:
    left:
      label: Left
    right:
      label: Right
    footer:
      label: Footer
custom_1col_landing:
  label: One Column Landing
  category: My Custom Layouts
  template: layouts/custom_1col_landing
  icon: layouts/custom_1col_landing.png
  regions:
    main:
      label: Main Region
    footer:
      label: Footer

Now you can create your page__custom_2col_brick.html.twig and page__custom_1col_landing.html.twig files in your layouts folder. Inside there you can define your template. For example custom_1col_landing.html.twig could contain

<div class="one-column-layout">
    <div class="row main">
        {{ content.main }}
    </div>
    <div class="row expanded one-column-footer">
        {{ content.footer }}
    </div>
</div>

Once finished you should have the following files. (The preview icons are optional)

/yourtheme/yourtheme.layouts.yml
/yourtheme/layouts/custom_2col_brick.html.twig
/yourtheme/layouts/custom_1col_landing.twig
  • <!-- FILE NAME SUGGESTIONS: * page--home.html.twig * page--.html.twig x page.html.twig --> All pages and layouts works just fine but there is no such a page template suggestion! There should be something like page--custom_2col_brick.html.twig – kLezer Aug 10 '16 at 19:59
  • this screenshot can be more meaningful. screenshot – kLezer Aug 10 '16 at 20:15
  • I'm not sure I understand. Every page that is set to use the custom_2col_brick.html.twig will be using that template. Why would you need a page--custom_2col_brick.html.twig? If you need multiple pages to use different versions of the template you should be using panels to do so. – Matt Aug 10 '16 at 20:18
  • custom_2col_brick.html.twig render only Content region in the page template. but I want to change other parts of the page template. Panels is an API in Drupal 8 So, I already use Page Manager and Panelizer. I need to change some things on the default page template. It will be an alternative page template for custom_2col_brick layout. – kLezer Aug 10 '16 at 20:45
  • You could try to keep page.html.twig as blank as possible, and fill everything with panels and blocks. – Matt Aug 10 '16 at 21:50
0

Expanding upon gambry's answer:

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function mytheme_theme_suggestions_page_alter(&$suggestions, &$vars) {
    $request = \Drupal::routeMatch()->getRouteObject();
    if ($request->getDefault('_entity_view') === 'page_manager_page_variant') {
        $page_variant = $request->getDefault('page_manager_page_variant');
        $name = 'page_manager.page_variant.' . $page_variant;
        $config = \Drupal::configFactory()->getEditable($name);
        if ($config->get('variant') === 'panels_variant') {
            $layout_id = $config->get('variant_settings.layout');
            $suggestions[] = 'page__page-manager';
            $suggestions[] = 'page__page-manager__' . $layout_id;
        }
    }
}

This should give you the layout id. In my case, i have a panel using the default 1 column layout, and I can use the following twig templates:

  • page--page-manager--layout-onecol.html.twig
  • page--page-manager.html.twig
  • page.html.twig

I agree with Matt that for the meat of the page you should use the panel layout's twig files (the yourtheme.layouts.yml method). Only use the above if you're trying to override the overall page template based on the panel layout.

0

Use hook_theme_suggestions_HOOK_alter() and \Drupal::routeMatch()->getRouteObject().

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function mytheme_theme_suggestions_page_alter(&$suggestions, &$vars) {
  $request = \Drupal::routeMatch()->getRouteObject();
  if ($request->getDefault('_entity_view') === 'page_manager_page_variant') {
    $page_name = $request->getDefault('page_manager_page');
    $page_variant = $request->getDefault('page_manager_page_variant');
    $suggestions[] = 'page__page_manager';
    $suggestions[] = 'page__page_manager__' . $page_name;
    $suggestions[] = 'page__page_manager__' . $page_name . '__' . $page_variant;
  }
}
  • Please explain the code you included in your answer, to avoid it gets deleted via moderation as a low quality answer ... – Pierre.Vriens Mar 16 '17 at 16:14
  • Hey gambry, Thanks for help. This method seems to work but page_manager_page_variant does not mean anything. ( custom_page-panels_variant-0 , home_page-panels_variant-1 etc.) This will change on every page and I can not define a constant value. It makes more sense to use a value that I can define with page_manager ui. Would it make sense to use context for this purpose? and How do I access to variants contexts ? Thank you. – kLezer Apr 2 '17 at 12:11

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.