- π³π¬Nigeria chike Nigeria
Using Drupal 10.0.3, 'layout_builder_iframe_modal' 1.3.0 and Boostrap Barrio theme, I am having this issue as this module is broken in the iframe.
I attached screenshots of how it looks.
- π―π΄Jordan Rajab Natshah Jordan
β¨ Limit Layout Builder Blocks not to work in the dashboards route Needs work
Switching the theme for front-end them is hard.
Layout Builder iFrame Modal is not practical to use with Layout Builder Blocks.
the system and them for Layout Styles should attached and changed to work with the back-end them.To me it's not doable. Hard to manage.
- π―π΄Jordan Rajab Natshah Jordan
Switching back to Layout Builder Modal with supports for Claro and Gin
- πΊπΈUnited States dalemoore
I wonder if it would be possible to take a page from Layout Builder Component Attributes β and have a different setting in the contextual menu just for the block style settings? If you have that module enabled, for a block you get four options:
- Configure
- Manage attributes (this is the menu item the module adds)
- Move
- Remove block
Then you could continue to edit the block content through "Configure", which will open in a modal window, but control the Bootstrap Styles under a separate link within the contextual menu so that they're in the right-hand tray not the popup.
- πΊπ¦Ukraine strayder
The code below implements this. https://www.drupal.org/project/layout_builder_blocks/issues/3238141#comm... β¨ Support for Layout Builder iFrame Modal Active
web/modules/custom/YOUR MODULE/src/Form/ManageComponentStylesForm.php
<?php namespace Drupal\YOUR MODULE\Form; use Drupal\bootstrap_styles\StylesGroup\StylesGroupManager; use Drupal\Component\Utility\Html; use Drupal\Core\Ajax\AjaxFormHelperTrait; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityRepositoryInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\layout_builder\Controller\LayoutRebuildTrait; use Drupal\layout_builder\LayoutTempstoreRepositoryInterface; use Drupal\layout_builder\SectionStorageInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides a form for managing block attributes without using tabs. */ class ManageComponentStylesForm extends FormBase { use AjaxFormHelperTrait; use LayoutRebuildTrait; /** * The section storage. * * @var \Drupal\layout_builder\SectionStorageInterface */ protected SectionStorageInterface $sectionStorage; /** * The section delta. * * @var int */ protected int $delta; /** * The component uuid. * * @var string */ protected string $uuid; /** * The Layout Tempstore. * * @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface */ protected LayoutTempstoreRepositoryInterface $layoutTempstore; /** * The configuration factory. * * @var \Drupal\Core\Config\ConfigFactoryInterface */ protected $configFactory; /** * The entity repository. * * @var \Drupal\Core\Entity\EntityRepositoryInterface */ protected EntityRepositoryInterface $entityRepository; /** * The styles group manager. * * @var \Drupal\bootstrap_styles\StylesGroup\StylesGroupManager */ protected StylesGroupManager $stylesGroupManager; /** * Constructs a new ManageComponentAttributesForm. * * @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository * The layout tempstore. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The configuration factory. * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository * The entity repository. * @param \Drupal\bootstrap_styles\StylesGroup\StylesGroupManager $styles_group_manager * The styles group manager. */ public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, ConfigFactoryInterface $config_factory, EntityRepositoryInterface $entity_repository, StylesGroupManager $styles_group_manager) { $this->layoutTempstore = $layout_tempstore_repository; $this->configFactory = $config_factory; $this->entityRepository = $entity_repository; $this->stylesGroupManager = $styles_group_manager; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('layout_builder.tempstore_repository'), $container->get('config.factory'), $container->get('entity.repository'), $container->get('plugin.manager.bootstrap_styles_group') ); } /** * {@inheritdoc} */ public function getFormId(): string { return 'YOUR MODULE_manage_attributes_form'; } /** * Builds the attributes form without tabs. * * @param array $form * An associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * @param \Drupal\layout_builder\SectionStorageInterface|null $section_storage * The section storage being configured. * @param int|null $delta * The original delta of the section. * @param string|null $uuid * The UUID of the block being updated. * * @return array * The form array. * * @throws \Drupal\Component\Plugin\Exception\PluginException * @throws \Drupal\Core\Entity\EntityStorageException */ public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, int $delta = NULL, string $uuid = NULL): array { $this->sectionStorage = $section_storage; $this->delta = $delta; $this->uuid = $uuid; $section = $section_storage->getSection($delta); $component = $section->getComponent($uuid); $block_plugin_id = $component->getPluginId(); // Check access to functionality. $allowed = $this->checkBlockRestrictions($block_plugin_id); if ($allowed) { $configuration = [ 'bootstrap_styles' => [ 'block_style' => [], ], ]; if ($component->get('bootstrap_styles')) { $bootstrap_styles = $component->get('bootstrap_styles'); if (isset($bootstrap_styles['block_style'])) { $configuration['bootstrap_styles'] = $bootstrap_styles; } } // Add fields to manage attributes. $form['appearance'] = [ '#type' => 'details', '#title' => $this->t('Styles'), '#open' => TRUE, ]; $form['appearance'] += $this->stylesGroupManager->buildStylesFormElements( $form['appearance'], $form_state, $configuration['bootstrap_styles']['block_style'], 'layout_builder_blocks.styles' ); // Attach required libraries. $form['#attached']['library'][] = 'bootstrap_styles/layout_builder_form_style'; } $form['#tree'] = TRUE; $form['#id'] = Html::cleanCssIdentifier($this->getFormId()); $form['actions']['submit'] = [ '#type' => 'submit', '#value' => $this->t('Update'), '#button_type' => 'primary', ]; if ($this->isAjax()) { $form['actions']['submit']['#ajax']['callback'] = '::ajaxSubmit'; } return $form; } /** * Checks block restrictions. * * @param string $block_plugin_id * ID of the block plugin. * * @return bool * TRUE if the block is allowed. * * @throws \Drupal\Core\Entity\EntityStorageException */ protected function checkBlockRestrictions(string $block_plugin_id): bool { $config = $this->configFactory->get('YOUR MODULE.settings'); $bundle = FALSE; if (str_starts_with($block_plugin_id, "block_content:")) { $uuid = str_replace('block_content:', '', $block_plugin_id); $bundle = $this->entityRepository->loadEntityByUuid('block_content', $uuid)->bundle(); } return empty($config->get('block_restrictions')) || in_array($block_plugin_id, $config->get('block_restrictions'), TRUE) || ($bundle && in_array('inline_block:' . $bundle, $config->get('block_restrictions'), TRUE)); } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state): void { $delta = $this->getSelectedDelta($form_state); $section = $this->sectionStorage->getSection($delta); $component = $section->getComponent($this->uuid); $bootstrap_styles = [ 'block_style' => $this->stylesGroupManager->submitStylesFormElements($form['appearance'], $form_state, ['appearance'], [], 'layout_builder_blocks.styles'), ]; $component->set('bootstrap_styles', $bootstrap_styles); $this->layoutTempstore->set($this->sectionStorage); $form_state->setRedirectUrl($this->sectionStorage->getLayoutBuilderUrl()); } /** * AJAX submit callback. */ public function ajaxSubmit(array &$form, FormStateInterface $form_state): AjaxResponse { return $this->rebuildAndClose($this->sectionStorage); } /** * {@inheritdoc} */ protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state): AjaxResponse { return $this->rebuildAndClose($this->sectionStorage); } /** * Gets the selected delta. * * @param \Drupal\Core\Form\FormStateInterface $form_state * The form state. * * @return int * The section delta. */ protected function getSelectedDelta(FormStateInterface $form_state): int { if ($form_state->hasValue('region')) { return (int) explode(':', $form_state->getValue('region'))[0]; } return (int) $this->delta; } }
YOUR MODULE.module
/** * Implements hook_module_implements_alter(). */ function YOUR MODULE_module_implements_alter(&$implementations, $hook): void { if ($hook === 'form_alter' && isset($implementations['layout_builder_blocks'])) { unset($implementations['layout_builder_blocks']); } }
YOUR MODULE.routing.yml
YOUR MODULE.manage_attributes: path: '/YOUR MODULE/update/block-styles/{section_storage_type}/{section_storage}/{delta}/{uuid}' defaults: _form: '\Drupal\YOUR MODULE\Form\ManageComponentStylesForm' _title: 'Manage styles' requirements: _permission: 'manage layout builder component attributes' _layout_builder_access: 'view' options: _admin_route: TRUE parameters: section_storage: layout_builder_tempstore: TRUE
YOUR MODULE.links.contextual.yml
layout_builder_block_styles: title: 'Manage styles' route_name: 'YOUR MODULE.manage_attributes' group: 'layout_builder_block' options: attributes: class: ['use-ajax'] data-dialog-type: dialog data-dialog-renderer: off_canvas