0

Class Documentation: SettingsCommand

I'm trying to figure out how to use this Ajax Command correctly. I must be confused from the documentation, so I'm hoping someone can shed some light where I'm mistaken.

__construct(array $settings, $merge = FALSE)

array $settings: An array of key/value pairs of JavaScript settings.
bool $merge: Whether the settings should be merged into the global drupalSettings.

Given the array already in drupalSettings: ['drupalSettings']['myData'] = [1,2,3,4,5];
And the following ajaxCallback I would like to replace the 'myData' array with [2, 4]:


    namespace Drupal\settings_controller_test\Form;

    use Drupal\Core\Form\FormBase;
    use Drupal\Core\Form\FormStateInterface;
    use Drupal\Core\Ajax\AjaxResponse;
    use Drupal\Core\Ajax\SettingsCommand;

    class SettingsControllerTestForm extends FormBase
    {
        public function getFormId() { return 'settings_controller_test_form'; }

        public function buildForm(array $form, FormStateInterface $form_state)
        {
            $form['invoker'] = [
                '#type' => 'submit',
                '#value' => t('Invoke Callback'),
                '#ajax' => [
                    'callback' => [$this, 'ajaxCallback']
                    ]
                ];

            $form['#attached']['drupalSettings']['myData'] = [1,2,3,4,5];
            $form['#attached']['library'][] = 'settings_controller_test/test';
            return $form;
        }

        public function ajaxCallback(array &$form, FormStateInterface $form_state)
        {
            $response = new AjaxResponse();

            #clear old myData settings
            $response->addCommand(new SettingsCommand(['myData' => []], TRUE));

            #add new data for myData settings
            $response->addCommand(new SettingsCommand(['myData' => [2,4]], TRUE));

            return $response;
        }

        public function validateForm(array &$form, FormStateInterface $form_state){}
        public function submitForm(array &$form, FormStateInterface $form_state){}
    }

I'm testing the state of 'myData' in JavaScript using the following:


(function ($, Drupal, drupalSettings) {
    Drupal.behaviors.myBehaviour = {
      attach: function (context) {
        //output: [1, 2, 3, 4, 5]
        console.log(drupalSettings.myData);


        $(document).once().ajaxComplete(function(event, xhr, settings) {
          //output: [2, 4, 3, 4, 5]
          console.log(drupalSettings.myData);
        });

      }
    };
  })(jQuery, Drupal, drupalSettings);

UPDATE: The attempt to clear the myData array fails. Then when I attempt to set myData = [2,4] with merge set as TRUE the leading two elements change to 2,4 and the remaining elements in the array are still there.
NOTE: If I change: $response->addCommand(new SettingsCommand(['myData' => [2,4]], TRUE)); to $response->addCommand(new SettingsCommand(['myData' => [2,4]], FALSE)); the myData array remains completely unchanged [1,2,3,4,5]

8
  • Is that the only JS you have to test it?
    – Kevin
    Commented Jan 9, 2019 at 20:53
  • I've added another JS test case to the question. I added a test button to trigger logging the current settings.myData array to the console. Before and after the ajaxCallback is invoked. The result remains the same.
    – Devin
    Commented Jan 9, 2019 at 21:28
  • The settings command without merging only makes sense if you use a local drupalSettings, see the discussion here drupal.stackexchange.com/questions/272020/…
    – 4uk4
    Commented Jan 9, 2019 at 21:45
  • @4k4 To my understanding merging will append the array, I'm wanting to replace the array. I believe I'm using drupalSettings. I'm attaching myData via the following: $form['#attached']['drupalSettings']['myData'] = [1,2,3,4,5]
    – Devin
    Commented Jan 9, 2019 at 22:01
  • @4k4 If the method I'm attempting to change the ['drupalSettings']['myData'] is incorrect. Could you direct me to a compatible solution to change the settings variable during an ajax callback?
    – Devin
    Commented Jan 9, 2019 at 22:07

2 Answers 2

1

Yes you need one more command to set the data back to nothing before you can overide it from trial and error the "merge" FALSE does nothing. so ...

// $response = new AjaxResponse();
// If want to replace you need to empty the array first.
$response->addCommand(new SettingsCommand([
  'MyData' => [],
], TRUE));
// then add new ones.
$response->addCommand(new SettingsCommand([
  'MyData' => [
    'New' => 'New values'
  ],
], TRUE));

See my New full example: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Ajax%21SettingsCommand.php/class/SettingsCommand/8.6.x#comment-64379

2
  • Thank you for your examples here and on the API reference page. I've reviewed them and made the necessary changes with still no luck. I've updated the question with the new details.
    – Devin
    Commented Jan 10, 2019 at 7:46
  • I need to reset like this: $response->addCommand(new SettingsCommand([ 'MyData' => null, ], TRUE)); Commented Mar 11 at 16:26
0

I faced the same issue and tried the answer from @taggartJ but not work. I use an alternative method to solve this issue as below:

public function ajaxCallback(array &$form, FormStateInterface $form_state)
    {
        $response = new AjaxResponse();

        // Send new value by DataCommand
        // We need to set $selector and $key
        // https://www.drupal.org/docs/drupal-apis/ajax-api/core-ajax-callback-commands
        $response->addCommand(new DataCommand($selector, $key, [2,4]));
        
        return $response;
    }

In JavaScript we just need to determine $('selector').data('key') is undefined or not, then we could update drupalSettings value.

    if ($('selector').data('key') != null) {
      drupalSettings.myData = $('selector').data('key');
    } else {
      drupalSettings.myData = [];
    }

Hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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