Create config object with array containing key-value pairs

by usernameabc   Last Updated March 14, 2019 18:07 PM

We have a custom module, mymodule, that we want to use to create a config object for so that it can contain an array of key-value pairs. We need to be able to click button Add More on the form that will add more key and value fields that will be mapped together.

How can we create a form that would not only display existing key-value pairs, but also provide option to add more?

Goals:

  1. On the admin Form, MyModuleForm be able to see existing key-value pairs.
  2. Add more key-value pairs.
  3. Key and value are text fields.
  4. Use the config_object within the mymodule.module file and fetch all the key-value pairs.

Below is what we tried, but got stuck on how to add the Add more functionality and how to properly store customKey and customValue into an array.

MyModuleForm.php

class MyModuleForm extends ConfigFormbase {
  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames() {
    return [
      'mymodule.settings'
    ];
  }

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

  public function buildForm(array $form, FormStateInterface $form_state) {
    $config = $this->config('mymodule.settings');
    $form['customKey'] = [
      '#title' => $this->t('Key value for array.'),
      '#type' => 'textfield',
      '#default_value' => $config->get('customKey'),
      '#maxlength' => 255,
      '#required' => TRUE,
    ];
    $form['customValue'] = [
      '#title' => $this->t('value for array.'),
      '#type' => 'textfield',
      '#default_value' => $config->get('customValue'),
      '#maxlength' => 255,
      '#required' => TRUE,
    ];

    return parent::buildForm($form, $form_state);
  }

  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Retrieve the configuration
    $this->configFactory->getEditable('mymodule.settings')
      ->set('customKey', $form_state->getValue('customKey'))
      ->set('customValue', $form_state->getValue('customValue'))
      ->save();

    parent::submitForm($form, $form_state);
  }
}


Answers 1


To add an add more button you'll need to create a callback function that will increase the number of fields necessary and rebuild that part of the form based on that information. You can make a new config variable based on some sort of index as you do a loop through all the necessary fields.

I haven't tested this so the syntax might be off but here's the basic idea in an example I wrote.

public function buildForm(array $form, FormStateInterface $form_state) {
        if (empty($number_of_member_fields)) {
            $number_of_member_fields = $form_state->set('number_of_member_fields', 1);
        }
        $forms['members_fieldset'] = [
            '#type' => 'fieldset',
            '#title' => t('Member types'),
            '#attributes' => [
                'id' => 'names-fieldset-wrapper'
            ],
        ];
        for ($i = 0; $i < $number_of_member_fields; $i++) {
            $form['members_fieldset']['memberType'.$i] = [
                '#type'          => 'textfield',
                '#title'         => t('Name'),
                '#default_value' => $config->get('memberType'.$i),
            ];
        }
        $form['members_fieldset']['actions']['add_name'] = [
            '#type'     => 'submit',
            '#value'    => t('Add one more'),
            '#submit'   => array('::addOne'),
            '#ajax'     => [
                'callback' => '::addmoreCallback',
                'wrapper'  => 'names-fieldset-wrapper',
            ],
        ];
    }
    public function addmoreCallback(array&$form, FormStateInterface $form_state) {
        return $form['members_fieldset'];
    }
    public function addOne(array&$form, FormStateInterface $form_state) {
        $number_of_member_fields = $form_state->get('number_of_member_fields');
        $number_of_member_fields++;
        $form_state->set('number_of_member_fields', $number_of_member_fields);
        $form_state->setRebuild();
    } 
Matt
Matt
March 14, 2019 18:05 PM

Related Questions


Updated October 02, 2018 21:07 PM

Updated January 05, 2019 01:07 AM

Updated December 28, 2018 23:07 PM

Updated July 06, 2018 18:07 PM

Updated August 03, 2018 19:07 PM