1

On my "teaser" view mode I want to display my Image field but if the Image field is empty I want to display my Title field instead.

I have tried using hook_preprocess_node but it appears that this is not called when rendering the node in the "teaser" display mode when using Display Suite.

Another thought I had was to create a custom DsField plugin... but in that case I do not have the context of the other fields (unless I do?) so I cannot say "if img is empty display title, else display img" Using the suggestion below I came up with:

class ImageElseTitle extends DsFieldBase {

  public function build() {
    /** @var /Drupal/node/Entity/node $node */
    $node = $this->entity();

    if ($node->get('field_event_image')->isEmpty()) {
      return $node->get('title')->view('teaser');
    }
    else {
      return $node->get('field_event_image')->view('teaser');
    }
  }

}

But in this case the settings for the title field are not obeyed. For example, it is wrapped in a span instead of an h2 as specified in the display settings. Similarly it is not a link even though "link" is checked in the display settings...

I tried adding a preprocess to the title field that checks if the image field is empty, but I think the preprocess function is too late to say "the image field is not empty, so never mind, dont display the title"

Thoughts?

-- Continued --

I also tried this, but the fields are not hidden as I'd expect them to be:

function mymodule_ds_pre_render_alter(&$layout_render_array, $context, &$vars) {
  if ($context['entity_type'] == 'node' && $context['bundle'] == 'event' && $context['view_mode'] == 'teaser') {
    if ($context['entity']->get('field_event_image')->isEmpty()) {
      $layout_render_array['field_event_image']['#access'] == FALSE;
    }
    else {
      $layout_render_array['node_title']['#access'] = FALSE;
      $layout_render_array['title']['#access'] = FALSE;
    }
  }
}
2

I've done this a couple ways.

First, you can you hook_ds_pre_render_alter (I can't find a better link to ds.api.php!) like hook_preprocess_node and just hide your title field if the image field is set. If you're using this option be sure to dig into the layout render array to the correct spot. For example if you have the ds node_title field within the ds_content region, hide it like

$layout_render_array['ds_content']['node_title']['#access'] = FALSE;

of if you have the same field within a title_wrapper field group, hide it like

$layout_render_array['ds_content']['group_title_wrapper']['node_title']['#access'] = FALSE;

Or you can create a custom ds field (yes, you have access to the whole entity). I usually enable the hidden region at /admin/structure/ds/settings, then I add both my title field and image field to the hidden region on my view mode and then just render whichever one I need in my ds field's build() method via the field's view method, in this case it would be like

$this->entity()->field_MY_IMAGE_FIELD->view('teaser');

or

$this->entity()->title->view('teaser');

Instead of passing a view mode's name, you can pass a display configuration array straight to the field's view method.

  • Thanks!! This got me a lot further, but the title field is not behaving. I added some code to the question above... – bleen Jun 2 '18 at 2:29
  • If the field is not added to a region, the settings won't be respected, the field is never prepared for view, that's why you need to enable the ds_hidden region and add your fields there. Or you can define the settings as an array, instead of passing the view mode name. – sonfd Jun 2 '18 at 3:02
  • I did exactly that (added to the hidden region). As an experiment i even added the two fields to the same (non-hidden) region as the ImageElseTitle field but the settings are still not respected for the title. Also tried the hook you suggested and that doesn't seem to work either (see code added to question) :( – bleen Jun 2 '18 at 3:23
  • 1
    Sorry to hear that. That's odd re: the hidden region. Using hook_ds_pre_render_alter you need to drill down deeper into where the field is within a region. Something like $layout_render_array['REGION']['node_title']['#access'] = FALSE. Maybe you have a field group too, in that case it would be something like $layout_render_array['REGION']['GROUP']['node_title']['#access'] = FALSE – sonfd Jun 2 '18 at 4:22
  • Great success!!! The suggestion about the hook worked well (thanks for pointing me to the [REGION] – bleen Jun 3 '18 at 0:28

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.