I am creating a field formatter - a Drupal 8 version of a D7 field formatter module I wrote. I'm having a hard time getting it to work properly - there are a couple of issues, and I need some assistance in figuring out why this does not work.

As you can see in the code below, I've tried a couple different things in the render array - only when I have very simple html, in a "#markup" item, does it display. When I try the <iframe> it displays nothing - the field is completely empty, both visually and in the rendered HTML. And when I instead specify a '#theme' element my hook_theme() never fires. Additionally, I find that the viewElements method is only being called once - I have to do a cache rebuild in order to get the method to run again.

My ultimate goal here is put the field formatting into a template and just pass variables into it via the theme hook.

Seems like there's more than one issue going on here but I'm not sure where one ends and another begins.  

This is the heart of the field formatter, in GdocFieldFormatter.php

    public function viewElements(FieldItemListInterface $items, $langcode) {
        $elements = array();
    
        foreach ($this->getEntitiesToView($items, $langcode) as $delta => $file) {
          $file_uri = $file->getFileUri();
          $filename = $file->getFileName();
          $uri_scheme = \Drupal::service("file_system")->uriScheme($file_uri);
          if ($uri_scheme == 'public') {
            $url = file_create_url($file->getFileUri());
            $elements[$delta] = array(
              '#markup' => '<strong>https://docs.google.com/gview?embedded=true&url=' . $url . '</strong>',
    //          '#markup' => '<iframe class="gdoc-field" style="width:300px;height:400px;" src="https://docs.google.com/gview?embedded=true&url=' . $url . '"></iframe>',
    /*          '#theme' => 'gdoc_field',
              '#url' => file_create_url($file->getFileUri()),
              '#filename' => $filename,*/
            );
    
          }
          else {
            drupal_set_message(
              t('The file (%file) is not publicly accessible. It must be publicly available in order for the Google Docs viewer to be able to access it.',
              array('%file' => $filename)
              ),
              'error',
              FALSE
            );
          }
        }
    
        return $elements;
      }

Here's the theme hook I wrote - but it's not firing and I don't know why. Note it is in gdoc_field.module

    function gdoc_field_theme($existing, $type, $theme, $path) {
      return array(
        'gdoc_field_formatter' => array(
          'variables' => array('url' => NULL, 'name' => NULL),
          'template' => 'gdoc-field',
        ),
      );
    }

So - several questions:

 - Why is the theme hook not being called?
 - Why is the &lt;iframe&gt; being stripped?
 - Why is the field formatter method viewElements only being called
   once, after a cache rebuild, instead of on every page view (even with
   caching turned off)?