0

In my custom form, I am trying to create webform entities. Since webforms need unique machine names, I'm using the MachineName (machine_name) form element. The D8 MachineName element documentation suggests that we can get the field to auto-populate based on the text input of another field, AND there can be an AJAX callback to call a function that can check to see if the machine name is unique.

Neither is working for me. These are the form elements I am using.

//----------------- general settings ------------------
$form['settings'] = array(
  'label' => ['#type' => 'textfield','#title' => 'Form Title'],
  'id'=> array(
    '#type' => 'machine_name',
    'label' => 'hh',
    '#source' => ['label'],
    '#maxlength' => 64,
    '#description' => $this->t('A unique name for this item. It must only contain lowercase letters, numbers, and underscores.'),
    '#machine_name' => array(
      'exists' => array(
        $this,
        'webform_id_exists',
      ),
    ),
  ),
);

Can anyone advise? I have a callback function named, but no idea what it should look like.

2

We can look at Drupal\node\NodeTypeForm.php for an example.

We see the name and type fields defined like:

$form['name'] = array(
  '#title' => t('Name'),
  '#type' => 'textfield',
  // ...
);
$form['type'] = array(
  '#type' => 'machine_name',
  // ...
  '#machine_name' => array(
    'exists' => [
      'Drupal\node\Entity\NodeType',
      'load',
    ],
    'source' => array(
      'name',
    ),
  ),
  // ...
);

This shows us how to define the special machine_name type properties in the array. We can see that both exists and source are defined inside #machine_name. Additionally, we see that the exists callback is just calling the NodeType::load() (which is actually inherited straight from Drupal\Core\Entity\Entity::load()).

For our exists callback, given this example, we'll want to use the equivalent method for whatever kind of entity we're creating a machine name for. Given your example, we're creating webforms, so we'd use the Drupal\webform\Entity\Webform::load() method for the exists callback.

We also see, from the machine_name element documentation, that the source property needs to be the #array_parents of the source field. Since your fields are nested inside settings, you'll need to include it in the source property.

Given the above, your updated code should be:

$form['settings'] = [
  'label' => [
    '#type' => 'textfield',
    '#title' => 'Form Title'
  ],
  'id'=> [
    '#type' => 'machine_name',
    'label' => 'hh',
    '#maxlength' => 64,
    '#description' => $this->t('A unique name for this item. It must only contain lowercase letters, numbers, and underscores.'),
    '#machine_name' => [
      'exists' => [
        'Drupal\webform\Entity\Webform',
        'load',
      ],
      'source' => [
        'settings',
        'label',
      ],
    ],
  ],
];
  • This works exactly as advertised. I particularly appreciate that there is no need to create a local function to serve the :exists feature. – Michael D. Moradzadeh Jan 2 at 15:29

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.