Grid not displaying in admin – custom Resource Model

I have a custom resource model mapping to a table named soldiers_thewatcher_watch with a primary key: watch_id.

I added the Grid UI component as well as a controller and admin link, but when I access the view (/admin/thewatcher/grid/index/) the page is basically blank in admin (the admin page loads but there is no content within the content area). I’ve added 1 row of data directly in the database.

I likely have a typo somewhere, but have been looking through everything for hours and cannot find where the problem is. A lot of code to follow, sorry, any help is greatly appreciated.

Route:

app/code/Soldiers/Thewatcher/etc/adminhtml/routes.xml

< ?xml version="1.0"?>

    
        
            
        
    

Controller:

Soldiers/Thewatcher/Controller/Adminhtml/Grid/Index.php

  namespace SoldiersThewatcherControllerAdminhtmlGrid;

  class Index extends MagentoBackendAppAction
  {
    /**
    * @var MagentoFrameworkViewResultPageFactory
    */
    protected $resultPageFactory;

    /**
     * Constructor
     *
     * @param MagentoBackendAppActionContext $context
     * @param MagentoFrameworkViewResultPageFactory $resultPageFactory
     */
    public function __construct(
        MagentoBackendAppActionContext $context,
        MagentoFrameworkViewResultPageFactory $resultPageFactory
    ) {
         parent::__construct($context);
         $this->resultPageFactory = $resultPageFactory;
    }

    /**
     * Load the page defined in view/adminhtml/layout/exampleadminnewpage_helloworld_index.xml
     *
     * @return MagentoFrameworkViewResultPage
     */
    public function execute()
    {
         return  $resultPage = $this->resultPageFactory->create();
    }
  }

Layout:

Soldiers/Thewatcher/view/adminhtml/layout/soldiers_thewatcher_grid_index.xml

< ?xml version="1.0"?>



    



Data Provider:

Soldiers/Thewatcher/Ui/Component/Listing/DataProviders/Soldiers/Thewatcher/Watch/Grid.php

< ?php
namespace SoldiersThewatcherUiComponentListingDataProvidersSoldiersThewatcherWatch;


/**
 * Class Grid
 */
class Grid extends MagentoUiDataProviderAbstractDataProvider
{    
    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        SoldiersThewatcherModelResourceModelWatchCollectionFactory $collectionFactory,
        array $meta = [],
        array $data = []
    ) {
        parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
        $this->collection = $collectionFactory->create();
    }
}

Action Bar:

Soldiers/Thewatcher/Ui/Component/Listing/Column/Soldiersthewatcherwatchgrid/PageActions.php

< ?php
namespace SoldiersThewatcherUiComponentListingColumnSoldiersthewatcherwatchgrid;


/**
 * Class PageActions
 */
class PageActions extends MagentoUiComponentListingColumnsColumn
{
    public function prepareDataSource(array $dataSource)
    {
        if (isset($dataSource["data"]["items"])) {
            foreach ($dataSource["data"]["items"] as & $item) {
                $name = $this->getData("name");
                $id = "X";
                if(isset($item["watch_id"]))
                {
                    $id = $item["watch_id"];
                }
                $item[$name]["view"] = [
                    "href"=>$this->getContext()->getUrl(
                        "soldiers_thewatcher_watch_grid/watch/edit",["watch_id"=>$id]),
                    "label"=>__("Edit")
                ];
            }
        }

        return $dataSource;
    }    

}

Grid:

Soldiers/Thewatcher/view/adminhtml/ui_component/soldiers_thewatcher_watch_grid.xml

< ?xml version="1.0"?>
    
        
            soldiers_thewatcher_watch_grid.soldiers_thewatcher_watch_grid_data_source
            soldiers_thewatcher_watch_grid.soldiers_thewatcher_watch_grid_data_source
        
        soldiers_thewatcher_watch_grid_columns
        
            
                add
                Add New
                primary
                */Watch/new
            
        
    
    
        
            SoldiersThewatcherUiComponentListingDataProvidersSoldiersThewatcherWatchGrid
            soldiers_thewatcher_watch_grid_data_source
            watch_id
            id
            
                
                    
                    
                        watch_id
                    
                
            
        
        
            
                Magento_Ui/js/grid/provider
            
        
    
    
        
            true
        
        
        
    
    
        
            
                
                    false
                    55
                    watch_id
                    10
                
            
        
        
            
                
                    textRange
                    asc
                    ID
                
            
        
        
            
                
                    false
                    107
                    watch_id
                    200
                
            
        
    

Resource Model (Collection)

Soldiers/Thewatcher/Model/ResourceModel/Watch/Collection.php

< ?php
namespace SoldiersThewatcherModelResourceModelWatch;

/**
 * Class Collection
 */
class Collection extends MagentoFrameworkModelResourceModelDbCollectionAbstractCollection
{
    protected function _construct()
    {
        $this->_init('SoldiersThewatcherModelWatch','SoldiersThewatcherModelResourceModelWatch');
    }
}

Resource Model (Entity)

Soldiers/Thewatcher/Model/ResourceModel/Watch.php

< ?php
namespace SoldiersThewatcherModelResourceModel;

/**
 * Class Watch
 */
class Watch extends MagentoFrameworkModelResourceModelDbAbstractDb
{
    protected function _construct()
    {
        $this->_init('soldiers_thewatcher_watch','watch_id');
    }
}

Model

app/code/Soldiers/Thewatcher/Model/Watch.php

< ?php
namespace SoldiersThewatcherModel;

/**
 * Class Watch
 */
class Watch extends MagentoFrameworkModelAbstractModel implements
    SoldiersThewatcherApiDataWatchInterface,
     MagentoFrameworkDataObjectIdentityInterface
{
    const CACHE_TAG = 'soldiers_thewatcher_watch';

    protected function _construct()
    {
        $this->_init('SoldiersThewatcherModelResourceModelWatch');
    }

    public function getIdentities()
    {
        return [self::CACHE_TAG . '_' . $this->getId()];
    }
}