Alter paragraph fields in closed mode I was wondering if there is a way to alter paragraph fields when the paragraph is set to "closed" in the Edit mode setting of form display. Because in that case the hook_field_widget_WIDGET_TYPE_form_alter does not return any of the inline paragraph fields inside the $element['subform']

To give a little more details, there's a paragraph field that holds some more native fields within itself. When I am trying to add/edit the node with which it is attached, i want to alter some fields within the paragraph. Since the paragraph is closed the fields within will be rendered via ajax call on the fly. I was looking for a way to alter them during this ajax call, that is just before they get rendered in the form so that I can alter their attributes.

Any idea?
I think there are two approaches you could take here. In the past I've successfully extended the InlineParagraphsWidget field widget in order to alter the form display for Paragraphs. I think that hook_ajax_render_alter() might also be a good solution.

I have not used hook_ajax_render_alter(), but I have successfully extended InlineParagraphsWidget for the purpose of altering the AJAX response. Specifically, look into overriding the ::addMoreAjax() and ::formElement() methods.

Below is a simplified version of the ::addMoreAjax() callback that I used. Use $insert_element = parent::addMoreAjax($form, $form_state); to get a reference to the triggering element.

public static function addMoreAjax(array $form, FormStateInterface $form_state)
    {
        $insert_element = parent::addMoreAjax($form, $form_state);

        // TODO: This is NOT the cleanest way to find the wrapper ID.
        // Find a cleaner way to get these values.
        $wrapper_id = explode('"', $insert_element['#prefix'])[1];
        $pos = strrpos($wrapper_id, '--');
        $wrapper_id = '#' . substr($wrapper_id, 0, $pos);

        // If you needed the field name.
        $field_name = end($insert_element['#parents']);

        $response = new AjaxResponse();
        $response-&gt;addCommand(new InsertCommand($wrapper_id, $insert_element));
        return $response;
    }


You will probably also want to provide validation by overriding ::elementValidate().

You will also likely need to implement hook_field_widget_info_alter() in order to make your new widget active.

function my_module_field_widget_info_alter(array &amp;$info)
{

    $info['entity_reference_paragraphs']['class'] = MyCustomInlineParagraphsWidget::class;
    $info['entity_reference_paragraphs']['provider'] = 'my_module';
}


Happy coding!