0

I have a route that takes a wildcard $product and then loads a default node that is stored in config. This is working (i.e. the node is rendered on that path) but instead of the node title it is displaying the route title 'Default Product List'.

Any ideas?

Routing.yml

default_product_list.generate_default_product_list:
  path: '/destinations/{region}/{area}/{town}/{product}'
  defaults:
    _controller: '\Drupal\default_product_list\Controller\DefaultProductListController::generateDefaultProductList'
    _title: 'Default Product List'
  requirements:
    _permission: 'access content'
  method: [GET]

Controller

 /**
   * Generatedefaultproductlist.
   *
   */
  public function generateDefaultProductList($region, $area, $town, $product) {

    $vars = [
      $region,
      $area,
      $town,
      $product
    ];

    $config = $this->config('default_product_list.defaultproductlist');

    $data = $config->get();

    if ($product === 'accomodation') {
      if (isset($data['default_accomodation_product'])) {
        $node = $this->defaultProductListUtility->loadDefaultNode($data['default_accomodation_product']);
        if (isset($node)) {
          $view_builder = $this->entityTypeManager()->getViewBuilder('node');
          $build = $view_builder->view($node);
//          kint(array($build));
          return array($build);
        }
      }
    }

  }

2 Answers 2

1

Put a dynamic title callback in the controller:

Routing.yml

default_product_list.generate_default_product_list:
  path: '/destinations/{region}/{area}/{town}/{product}'
  defaults:
    _controller: '\Drupal\default_product_list\Controller\DefaultProductListController::generateDefaultProductList'
    _title_callback: '\Drupal\default_product_list\Controller\DefaultProductListController::title'
  requirements:
    _permission: 'access content'
  method: [GET]

Controller

  /**
   * Generatedefaultproductlist.
   *
   */
  public function generateDefaultProductList($region, $area, $town, $product) {

    // build content

    return $build;
  }

  /**
   * Provides the page title for this controller.
   *
   */
  public function title($region, $area, $town, $product) {

    // build title

    return $title;
  }    

This dynamic title callback works in all places, also where the content is not rendered and doing so only to retrieve the title would be too expensive, for example in breadcrumbs.

It's also the preferred way and might sometimes be the only way, see Discourage $main_content['#title'] in favor of route titles and title callbacks:

Proposed resolution

Remove the ability to set a dynamic page title using #title, always use _title or _title_callback.

1
  • Thanks this is a better answer as it updates breadcrumb too in one go.
    – chap
    Oct 24, 2017 at 7:56
2

As it is routing path, Drupal will always look for the title in routing.yml, if you want to set title for this you can do as follows,

$build['#attached']['html_head'][] = [
    [
      '#tag' => 'title',
      '#value' => "Node title"
    ],
    'title'
  ];

OR

$build['#title'] = 'Node Title';

Here you can replace "Node Title" with your dynamic node titles.

1

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.