MachineName field element: How do I use the source and exists properties? 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' =&gt; ['#type' =&gt; 'textfield','#title' =&gt; 'Form Title'],
  'id'=&gt; array(
    '#type' =&gt; 'machine_name',
    'label' =&gt; 'hh',
    '#source' =&gt; ['label'],
    '#maxlength' =&gt; 64,
    '#description' =&gt; $this-&gt;t('A unique name for this item. It must only contain lowercase letters, numbers, and underscores.'),
    '#machine_name' =&gt; array(
      'exists' =&gt; array(
        $this,
        'webform_id_exists',
      ),
    ),
  ),
);


Can anyone advise? I have a callback function named, but no idea what it should look like.
We can look at Drupal\node\NodeTypeForm.php for an example.

We see the name and type fields defined like:

$form['name'] = array(
  '#title' =&gt; t('Name'),
  '#type' =&gt; 'textfield',
  // ...
);
$form['type'] = array(
  '#type' =&gt; 'machine_name',
  // ...
  '#machine_name' =&gt; array(
    'exists' =&gt; [
      'Drupal\node\Entity\NodeType',
      'load',
    ],
    'source' =&gt; 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' =&gt; [
    '#type' =&gt; 'textfield',
    '#title' =&gt; 'Form Title'
  ],
  'id'=&gt; [
    '#type' =&gt; 'machine_name',
    'label' =&gt; 'hh',
    '#maxlength' =&gt; 64,
    '#description' =&gt; $this-&gt;t('A unique name for this item. It must only contain lowercase letters, numbers, and underscores.'),
    '#machine_name' =&gt; [
      'exists' =&gt; [
        'Drupal\webform\Entity\Webform',
        'load',
      ],
      'source' =&gt; [
        'settings',
        'label',
      ],
    ],
  ],
];