Building on @adrianp, this is how you would do it for the form pages (edit/add).
my_module.services.yml
services:
theme.negotiator.my_module:
class: Drupal\my_module\Theme\MyModuleThemeNegotiator
arguments: ['@config.factory']
tags:
- { name: theme_negotiator, priority: 1000 }
in my_module/Routing/MyModuleThemeNegotiator.php
namespace Drupal\my_module\Theme;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Theme\ThemeNegotiatorInterface;
use Symfony\Component\Routing\Route;
/**
* My ModuleTheme Negotiator for some content types add/edit.
*
* We must use a theme negotiator instead of routeSubscriberBase->alterRoutes
* to make the route admin, as the same route works all content types
* and we only want one.
*
* How determining themes work in Drupal:
* - When is comes time for Drupal to render your page and select a theme,
* it looks for all classes that implement ThemeNegotiatorInterface.
* - All implementations begin to be called in priority order, from the highest
* to the lowest.
* - If the applies method returns false, Drupal moves on to the next
* implementation.
* - If the applies method returns true, Drupal calls the determineActiveTheme
* method in the same implementation.
* - If determineActiveTheme returns null, Drupal moves on to the next
* implementation.
* - If determineActiveTheme returns a theme name, Drupal will use this theme,
* and no further implementations are called.
* - Drupal has its own default implementation. If no other implementations
* selects a theme, the default will select a theme.
*
* @see https://jimconte.com/blog/web/dynamic-theme-switching-in-drupal-8
*/
class MyModuleThemeNegotiator implements ThemeNegotiatorInterface {
/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactory
*/
protected $configFactory;
/**
* Service constructor.
*
* @param \Drupal\Core\Config\ConfigFactory $configFactory
* Configfactory.
*/
public function __construct(ConfigFactory $configFactory) {
$this->configFactory = $configFactory;
}
/**
* {@inheritdoc}
*/
public function applies(RouteMatchInterface $route_match) {
$route = $route_match->getRouteObject();
if (!$route instanceof Route) {
return FALSE;
}
$routes_to_match = ['node.add', 'entity.node.edit_form'];
if (in_array($route_match->getRouteName(), $routes_to_match)) {
return TRUE;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function determineActiveTheme(RouteMatchInterface $route_match) {
$applicable_bundles = [
'news',
'standard_page',
];
$switch_theme = FALSE;
switch ($route_match->getRouteName()) {
case 'node.add':
if ($entity_type_param = $route_match->getParameter('node_type')) {
if (in_array($entity_type_param->id(), $applicable_bundles)) {
$switch_theme = TRUE;
}
}
break;
case 'entity.node.edit_form':
if ($entity_param = $route_match->getParameter('node')) {
if (in_array($entity_param->bundle(), $applicable_bundles)) {
$switch_theme = TRUE;
}
}
break;
}
if ($switch_theme) {
// Return the machine name of the front-end theme.
return $this->configFactory->get('system.theme')->get('default');
}
// Not applicable.
return NULL;
}
}