Conditionally display a field 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-&gt;entity();

    if ($node-&gt;get('field_event_image')-&gt;isEmpty()) {
      return $node-&gt;get('title')-&gt;view('teaser');
    }
    else {
      return $node-&gt;get('field_event_image')-&gt;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(&amp;$layout_render_array, $context, &amp;$vars) {
  if ($context['entity_type'] == 'node' &amp;&amp; $context['bundle'] == 'event' &amp;&amp; $context['view_mode'] == 'teaser') {
    if ($context['entity']-&gt;get('field_event_image')-&gt;isEmpty()) {
      $layout_render_array['field_event_image']['#access'] == FALSE;
    }
    else {
      $layout_render_array['node_title']['#access'] = FALSE;
      $layout_render_array['title']['#access'] = FALSE;
    }
  }
}
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-&gt;entity()-&gt;field_MY_IMAGE_FIELD-&gt;view('teaser');


or    

$this-&gt;entity()-&gt;title-&gt;view('teaser');


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