2

I am saving node as unpublished without adding data in required fields. How can I achieve that in Drupal 8 ? Basically I need something like Save as Draft option for nodes in content types.

  • I guess you would have to do this programmatically. But why do you need to require the fields? Is it an option to make them optional fields? – Stef Van Looveren Oct 10 '17 at 9:46
  • You should add a custom validation function for your "Save unpublished" submit action. But the problem is, that the browsers have an icluded required field vaidation. So you should implement a hook_form_alter and set #required=FALSE on a specific condition. – sgoelz Oct 10 '17 at 12:41
  • 2
    @Stef, if this is what I think it is (like my need), this is because fields are still, ultimately, required, but you may want to be able to let the user save it and come back later. – UnsettlingTrend May 31 '18 at 16:38
0

The save_draft module should make this possible for Drupal 7 (with the patch from issue 1786442 applied). Issue 2220659 describes a Drupal 8 version, but the patch does not include the fix for allowing missing required fields. In Drupal 8, this has become a bit more difficult because of the added Entity validation.

I created following ugly solution for my use case, which eliminates NotNull errors related to required fields and sets the entity as validated if no errors remain. I make use of disable_html5_validation to disable client side validation.

function find_element_by_path($element, $path) {
  if (count($path) === 0) {
    return $element['widget'];
  }
  if (is_numeric($path[0])) {
    return find_element_by_path($element['widget'][array_shift($path)], $path);
  }
  return find_element_by_path($element[array_shift($path)], $path);
}

function save_draft_validate($form, &$form_state) {
  // Remove all NotNull validation errors related to required fields.
  $errors = $form_state->getErrors();
  foreach ($errors as $key => $error) {
    if ($error->getUntranslatedString() === 'This value should not be null.') {
      $element = find_element_by_path($form, explode('][', $key));
      if (isset($element['#originallyRequired']) && $element['#originallyRequired']) {
        unset($errors[$key]);
      }
      elseif ($element['#theme'] === 'file_widget_multiple') {
        if (isset($element[0]['#originallyRequired']) && $element[0]['#originallyRequired']) {
          unset($errors[$key]);
        }
      }
    }
    elseif ($error->getUntranslatedString() === 'An illegal choice has been detected. Please contact the site administrator.') {
      $element = find_element_by_path($form, explode('][', $key));
      if (isset($element['#originallyRequired']) && $element['#originallyRequired'] && $element['#value'] === '_none') {
        unset($errors[$key]);
      }
    }
  }
  $form_state->clearErrors();
  if (count($errors) === 0) {
    $form_state->setTemporaryValue('entity_validated', TRUE);
  } else {
    foreach($errors as $key => $error) {
      $form_state->setErrorByName($key, $error);
    }
  }
}

function save_draft_unpublish_submit($form, &$form_state) {
  $form_state->setValue('status', ['value' => 0]);
}

function remove_required(&$element) {
  // Recurse through all children.
  foreach (Element::children($element) as $key) {
    if (isset($element[$key]) && $element[$key]) {
      remove_required($element[$key]);
    }
  }
  // Make sure the title field remains required.
  $titleIds = ['edit-title', 'edit-title-0', 'edit-title-0-value'];
  if (!empty($element['#required']) && !in_array($element['#id'], $titleIds)) {
    $element['#originallyRequired'] = $element['#required'];
    $element['#required'] = FALSE;
  }
}

function MY_MODULE_form_after_build($form, &$form_state) {
  // Check that the form has been submitted.
  if ($form_state->isProcessingInput()) {
    // If the save draft button was pressed.
    if ($form_state->getTriggeringElement()['#id'] === 'edit-draft') {
      remove_required($form);
    }
  }
  return $form;
}

function add_draft(&$form) {
  $form['actions']['draft'] = [
    '#type' => 'submit',
    '#value' => t('Save draft'),
    '#weight' => '9',
    '#submit' => $form['actions']['submit']['#submit'],
    '#validate' => ['save_draft_validate'],
  ];
  array_unshift($form['actions']['draft']['#submit'], 'save_draft_unpublish_submit');
  $form['#after_build'][] = 'MYMODULE_form_after_build';
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function MYMODULE_form_node_MYFORM_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  add_draft($form);
}

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.