files – Form API – managed_file always empty on form validate/submit

I just gave up looking for a solution with this issue.

I’m building several forms with drupal 8.9, some of them are required to have the “managed_file” field in order to upload a single file.

The form is built using the tree option and also I have to use the “add more” button to build a new set of inputs if necessary.

So far I’ve built successfully the form and the ajax multi-field feature.

The problem is when I try to manage the uploaded file, al the answer I’ve found so far are similar to this post (How to use the managed_file field in a custom form plugin). When I try to process the file input it is always empty or null, but the files I upload using the buttons are saved in the folder set within the “#upload_location” tag and also they’re saved in the database as temporary files.

What I want to do is change the files to permanent and get the fid of them.

Sorry if this has been answered before but I coundn’t find any solution.

This is how the form field looks like:

$form('links') = array(
    '#type' => 'container',
    '#tree' => TRUE,
    '#title' => t('Recommended Links'),
    '#prefix' => '<div id="links-wrapper" class="fieldset-wrapper-er margin-fieldset">',
    '#suffix' => '</div>',
);
for ($i = 0; $i < $count_er; $i++) {
    $form('links')($i)('attach_file') = array(
        '#title' => t('Attach file'),
        '#type' => 'managed_file',
        '#description' => t('Upload an evidence document in pdf format of your entry'),
        '#upload_location' => 'public://recommended',
        '#upload_validators' => (
            'file_validate_extensions' => ('pdf'),
        ),
   );
}
$form('links')('add') = array(
    '#type' => 'submit',
    '#value' => '+ ' . t('Add Link'),
    '#submit' => array('::addLink'),
    '#ajax' => array(
        'callback' => '::linkCallback',
        'wrapper' => 'links-wrapper',
    ),
);

if ($multiple) {
    $form('links')('remove') = array(
        '#type' => 'submit',
        '#value' => '- ' . t('Remove Link'),
        '#submit' => array('::removeLink'),
        '#ajax' => array(
            'callback' => '::linkCallback',
            'wrapper' => 'links-wrapper',
        ),
    );
}

And lastly this is what my submitFunction looks like:

public function submitForm(array &$form, FormStateInterface $form_state) {
    $user = Drupal::currentUser();
    $user_data = User::load($user->id());
    $links = $form_state->getValue('links');
    $paragraphs = array();

    try {
        foreach($links AS $link) {
            if(is_array($link) OR is_object($link)) {
                $fid = reset($link('attach_file'));
                $file = File::load($fid);
                $file->setPermanent();
                $file->save();
                
                $paragraph = Paragraph::create((
                    'type' => 'recommended_links',
                    'field_status' => $link('status'),
                    'field_recommended_lin' => array(
                        'uri' => $link('url'),
                        'title' => $link('title')
                    ),
                    'field_attachment' => array(
                        'target_id' => $fid
                    ),
                ));
                $paragraph->save();
                $paragraphs() = $paragraph;
            }
        }
        $user_data->set('recommended_link', $paragraphs);
        $res = $user_data->save();
        
        if($res) {
            $msg = t('Your changes have been successfully saved!');
            drupal_set_message($msg);
        } else {
            $msg = t('Errors detected while saving the data');
            drupal_set_message($msg, 'error');
        }

        return ('response' => $msg);
    } catch(Throwable $e) {
        Drupal::logger('profile')->error('Form links: '. $e);
        $msg = t('Errors detected while saving the data');
        drupal_set_message($msg, 'error');
        return ('message' => $msg);
    }
}