Drupal 8: How to properly add a settings widget to a node add/edit form and save the value? So I reviewed the code in the core book, menu_ui, and path modules, and they all seem to handle adding a settings widget in a vertical tab differently. 

The book module uses a method called addFormElement(), which is called within a hook_form_BASE_FORM_ID_alter() hook.

The menu_ui module is similar, but uses hook_form_BASE_FORM_ID_alter() directly.

Path seems to use a method called formElement(), and I'm not even sure where/how this method is used at the moment. 

The real question I have is, how does one actually process the form setting and save it to the database? I have tried to find an example, but I'm at a loss.

Is there a help page with examples like the ones I found for adding an admin settings page?

If not, is there a recommended approach to displaying/saving a value in a vertical tab on a node add/edit form?
I'm going to take a stab and show how I solved it, but I'm still curious to know if there's a better way.

In a nutshell, I used hook_form_BASE_FORM_ID_alter(), hook_node_submit(), and hook_ENTITY_TYPE_insert() or hook_ENTITY_TYPE_update() in the .module file.

Then I have a class called HierarchyManager that does all the heavy lifting that the D7 .module and .inc files used to do. It's listed as a service named "nodehierarchy.manager".

Lastly, I have a class called HierarchyOutlineStorage that handles the database inserts and updates. Quite a bit of that code was copied directly from D7. 

In my .module file:

/**
 * Implements hook_form_BASE_FORM_ID_alter() for node_form().
 *
 * Adds the hierarchy form element to the node form.
 */
function nodehierarchy_form_node_form_alter(&amp;$form, FormStateInterface $form_state, $form_id) {

  // Load the node object associated with this form
  $node = $form_state-&gt;getFormObject()-&gt;getEntity();
  $account = \Drupal::currentUser();

  // Optional but keeps the .module code cleaner IMO      
  $hierarchy_manager = \Drupal::service('nodehierarchy.manager');

  // Do your permission checks here
  $has_permission = ...;
  if($has_permission) {
    $form = $hierarchy_manager-&gt;addHierarchyFormElement($form, $form_state, $node, $account, $collapsed);
  } 
}

/**
 * Implements hook_node_submit().
 */
function nodehierarchy_node_submit(NodeInterface $node, $form, FormStateInterface $form_state) {
  // Here the node object gets updated with the form value to be used later
  // If you aren't sure about the $form_state, download/enable devel and add
  // dsm($form_state-&gt;getValues()) to show all available values
  if (!$form_state-&gt;isValueEmpty('nodehierarchy_parents')) {
    $node-&gt;nodehierarchy_parents = $form_state-&gt;getValue('nodehierarchy_parents');
  }
}

/**
 * Implements hook_ENTITY_TYPE_insert() for node entities.
 *
 * Save the form settings
 */
function nodehierarchy_node_insert(NodeInterface $node) {
  $hierarchy_manager = \Drupal::service('nodehierarchy.manager');
  $has_permission = ...
  if ($has_permisson) {
    $hierarchy_manager-&gt;hierarchySaveNode($node);
  }
}

/**
 * Implements hook_ENTITY_TYPE_update().
 */
function nodehierarchy_node_update(EntityInterface $node) {
  $hierarchy_manager = \Drupal::service('nodehierarchy.manager');
  $hierarchy_manager-&gt;hierarchySaveNode($node);
}


In the HierarchyManager.php file:

public function addHierarchyFormElement(array $form, FormStateInterface $form_state, NodeInterface $node, AccountInterface $account, $collapsed = TRUE) {
  // Insert $form array here
  $form['hierarchy'] = array(...);
}

public function hierarchySaveNode(&amp;$node) {
  // Do all your processing here, then insert or update dB record
  $isNew = ...
  if ($isNew) {
    return $this-&gt;hierarchyOutlineStorage-&gt;insert($item);  
  }
  else {
    return $this-&gt;hierarchyOutlineStorage-&gt;update($item-&gt;hid, $item);
  }
}