0

I'm trying to create a language modal for Drupal 8.

I only want to show the modal if:

  • Language paramater is not present in URL
  • Language cookie is set by previous selection.

I don't really know what the best method is to create this. I started by creating a hidden ajax button which gets clicked by custom js if the language parameter is not present in the URL and the language cookie is not set:

namespace Drupal\dms_theme\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\lang_dropdown\Form\LanguageDropdownForm;
use Drupal\Core\Url;
use Drupal\Core\Language\Language;

/**
 * Class LangswitchModal.
 *
 * @package Drupal\dms_theme\Form
 */
class LangswitchModal extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'dms_theme_langswitch';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';

    $form['actions']['#type']  = 'actions';
    $form['actions']['submit'] = [
      '#type'  => 'submit',
      '#value' => $this->t('Switch language'),
      '#ajax'  => [
        'callback' => '::open_modal',
      ],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {

  }

  public function open_modal(&$form, FormStateInterface $form_state) {
    // Get active domain
    $domain_negotiator = \Drupal::service('domain.negotiator');

    $form = \Drupal::formBuilder()->getForm('Drupal\dms_theme\Form\LangswitchForm');

    // Build array
    $build = [];

    $build[] = [
      '#theme' => 'langswitch_modal',
      '#title' => 'Welcome',
      '#form' => render($form),
    ];

    $render  = \Drupal::service('renderer')->renderPlain($build);

    // Dialog
    $options = [
      'dialogClass' => 'popup-languageswitcher-modal',
      'width'       => '100%',
    ];

    $response = new AjaxResponse();
    $response->addCommand(new OpenModalDialogCommand(NULL, $render, $options));

    return $response;
  }
}

The modal is opened correctly and the content and form is printed.

Logic of the form:

namespace Drupal\dms_theme\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\lang_dropdown\Form\LanguageDropdownForm;
use Drupal\Core\Url;
use Drupal\Core\Language\Language;

/**
 * Class LangswitchForm.
 *
 * @package Drupal\dms_theme\Form
 */
class LangswitchForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'dms_theme_langswitchform';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    // Service
    $domain_negotiator = \Drupal::service('domain.negotiator');

    // Language options
    $language_options = [];
    foreach(domain_locale_custom_get_domains_languages()[$domain_negotiator->getActiveId()] as $domain_language) {
      $language_options[$domain_language->getId()] = $domain_language->getName();
    }

    $form['languages'] = [
      '#type' => 'select',
      '#title' => t('Please indicate from which location you are connecting:'),
      '#options' => $language_options,
      '#required' => TRUE,
    ];

    $form['actions'] = [];
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => t('Submit button'),
    ];

    return $form;
  }



  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {

  }
}

Now i can't submit the form correctly. It redirects to urls like /form_action_p_pvdeGsVG5zNF_XLGPTvYSKCf43t8qZYSwcfZl2uzM.

I geuss this is caused by the ajax callback url, which is used by some form parameters. But don't really know how to solve this.

Thnx.

Other question: What are in general the best practice to show a language modal. If language is not is in URL? If language is not set in Cookie? Or the combination described above?

1

You render early twice, which prevents that any attached metadata has a chance to get into the response. You can try without rendering or if you need to render, then attach the metadata to the response like in this example:

ModalRenderer::renderResponse

  public function renderResponse(array $main_content, Request $request, RouteMatchInterface $route_match) {
    $response = new AjaxResponse();

    // First render the main content, because it might provide a title.
    $content = drupal_render_root($main_content);

    // Attach the library necessary for using the OpenModalDialogCommand and set
    // the attachments for this Ajax response.
    $main_content['#attached']['library'][] = 'core/drupal.dialog.ajax';
    $response->setAttachments($main_content['#attached']);

    // If the main content doesn't provide a title, use the title resolver.
    $title = isset($main_content['#title']) ? $main_content['#title'] : $this->titleResolver->getTitle($request, $route_match->getRouteObject());

    // Determine the title: use the title provided by the main content if any,
    // otherwise get it from the routing information.
    $options = $request->request->get('dialogOptions', []);

    $response->addCommand(new OpenModalDialogCommand($title, $content, $options));
    return $response;
  }

Additional to the example you might need to add the attachments of the form too:

$response->addAttachments($form['#attached']);

"Other question: What are in general the best practice to show a language modal. If language is not is in URL? If language is not set in Cookie? Or the combination described above?"

There is also a server side approach. You can add some kind of overlay with the form before you deliver the page.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.