How to manipulate value before node is saved in Drupal 8?
Asked Answered
F

3

5

I have an editing node form. When user enters new value and clicks on submit to edit the node, I first want to get the old node back, manipulate the value and then just save/update the node.

Below is my solution, but it does not work.

function custom_module_form_node_form_alter(&$form, FormStateInterface $form_state) {
    $editing_entity = $form_state->getFormObject()->getEntity();

    if (!$editing_entity->isNew()) {
        $form['actions']['submit']['#submit'][] = 'custom_module_node_form_submit';
    }
}

function custom_module_node_form_submit($form, FormStateInterface $form_state) {
   $editing_entity = $form_state->getFormObject()->getEntity();

   $entity = Drupal::entityTypeManager()->getStorage('node')->load($editing_entity->id());
}

In the form_submit hook, I tried to get the old node back but it is already too late and the node is already updated/saved. How can I get the old node back and manipulate the value before updating/saving the node in Drupal 8?

Fluke answered 23/5, 2018 at 7:47 Comment(0)
F
5

I decide to manipulate the values in the form validate hook as following.

function custom_module_form_node_form_alter(&$form, FormStateInterface $form_state) {
    $editing_entity = $form_state->getFormObject()->getEntity();

    if (!$editing_entity->isNew()) {
        $form['#validate'][] = 'custom_module_node_form_validate';
    }
}

function custom_module_node_form_validate(array &$form, FormStateInterface $form_state) {
    $old_entity = $form_state->getFormObject()->getEntity();
    $old_values = $old_entity->get('field_name')->getValue()

    $new_values = $form_state->getValue('field_name');

    // Manipulate and store desired values to be save here.
    $to_save_value = ['a', 'b', 'c'];
    $form_state->setValue('field_name', $to_save_value);
}
Fluke answered 23/5, 2018 at 10:32 Comment(1)
I opted for this solution, as this hooks works not only in the context of a custom module like is hook_node_presave does, but it also can be implemented in the context of a custom theme fileJodee
O
4

Try using hook_entity_presave():

/**
 * Implements hook_entity_presave().
 */
function YOUR_MODULE_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
  switch ($entity->bundle()) {
    // Here you modify only your day content type
    case 'day':
      // Setting the title with the value of field_date.
      $entity->setTitle($entity->get('field_date')->value);
     break;
  }
}

Solution taken from here: https://drupal.stackexchange.com/questions/194456/how-to-use-presave-hook-to-save-a-field-value-as-node-title

Also you can get old value like: $entity->original. Check it out here:

https://drupal.stackexchange.com/questions/219559/how-to-get-the-original-entity-on-hook-entity-presave

Okelley answered 23/5, 2018 at 9:9 Comment(5)
thanks for your solution. I have looked at this hook. But it is too generic. I am looking for something more specific because presave hook is for all save operations. I am now trying form_validate hook which I can manipulate the value before saving. Tell me what you think about the form_validate hook.Fluke
Updated my answer about on how to get old value. Don't understand what you mean by "too generic"?!? Why can't you use it? Do you need to un-validate form in some case (prevent it successful saving)?Okelley
By too generic, I mean presave hook will be invoked when you save everything such as node, terms, user etc. That's why we use the switch statement in the presave hook. But your solution works well.Fluke
Yes, you can have that general that hooks all the entity types or add entity type to function name, as Kris explained. But point is the same.Okelley
Using hook_ENTITY_TYPE_presave is a better idea if you are only interested in node entity: https://mcmap.net/q/1907253/-how-to-manipulate-value-before-node-is-saved-in-drupal-8Alliance
M
3

Use hook_ENTITY_TYPE_presave, like so:

function yourmodulename_node_presave(Drupal\node\NodeInterface $entity) {
    if ($entity->getType() == 'your_content_type') {
       $entity->setTitle('Hello');
       $entity->set('body', 'this is body');
    } 
}

This is the best solution, because with hook_form_alter like MilanG you will be changing the value only when the node is saved from the particular form you are altering! If the node is saved programmatically from within the code or by some other method your hook_form_alter will not kick in.

Munguia answered 23/5, 2018 at 11:41 Comment(2)
This is not very helpful. All you did was copy the hook signature. It fails to show how to actually set a field value... and in particular one of the fields that does not have a magic method (like setTitle()).Lanitalank
@Lanitalank I improved the code based on your comment.Alliance

© 2022 - 2024 — McMap. All rights reserved.