Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

georgetown74's avatar

Nova Action does not pass content from textarea input field to backend for processing

This is a follow-up from https://laracasts.com/discuss/channels/nova/creating-items-and-related-records-in-bulk-using-nova...

I have a Nova action to import URLs in bulk and attach to a model. I created the source and registered it to the resource like this:

    public function actions(NovaRequest $request): array
    {
        return [
            (new ImportSources())->showInline()
        ];
    }

Here is my handle method for the action:

    public function handle(ActionFields $fields, Collection $models): mixed
    {
        DB::beginTransaction();

        try {
            // Split the string by new lines and filter out any empty values
            $rawData = $fields->get('URLs');
            Log::info('Raw input data:', ['data' => $rawData]);

            $lines = array_filter(preg_split('/\r\n|\r|\n/', $rawData));
            Log::info('Processing lines:', ['lines' => $lines]);

            foreach ($lines as $line) {
                // Extract URL using regular expression
                // This pattern matches URLs in Markdown links or standalone URLs
                if (preg_match('/\bhttps?:\/\/\S+|\((https?:\/\/\S+)\)/i', $line, $matches)) {
                    $url = trim($matches[0], '()'); // Remove parentheses if they exist

                    // Log extracted URL
                    Log::info('Extracted URL:', ['url' => $url]);

                    // Normalize the URL
                    $normalizedUrl = rtrim($url, '/');
                    $normalizedUrl = preg_replace('/#:~:text=.*$/', '', $normalizedUrl);

                    // Log normalized URL
                    Log::info('Normalized URL:', ['url' => $normalizedUrl]);

                    // Check if the URL exists in the sources table
                    $source = Source::firstOrCreate(['url' => $normalizedUrl]);

                    // Log source creation or retrieval
                    Log::info('Source retrieved or created:', ['source' => $source]);

                    foreach ($models as $model) {
                        // Attach the source to the Thread
                        $model->sources()->syncWithoutDetaching([$source->id]);

                        // Debugging: Check attached sources
                        $attachedSources = $model->sources()->get();
                        Log::info('Attached sources:', $attachedSources->toArray());
                    }
                } else {
                    // Log if no URL is matched
                    Log::warning('No URL matched in line:', ['line' => $line]);
                }
            }

            DB::commit();
            return Action::message('URLs have been processed and attached successfully!');
        } catch (\Exception $e) {
            DB::rollBack();
            // Log the exception
            Log::error('Error during URL processing:', ['error' => $e->getMessage()]);
            return Action::danger('An error occurred: ' . $e->getMessage());
        }
    }

Here is my field definition:

    public function fields(NovaRequest $request): array
    {
        return [
            Textarea::make('URLs')
                ->rules('required')
                ->help('Paste the sources here, one URL per line.'),
        ];
    }

When I log the above code I only see the below which seems to indicate the URLs I am importing are not getting passed from the textarea field to the backend for processing:

[2023-12-26 18:21:27] local.INFO: Raw input data: {"data":null} 
[2023-12-26 18:21:27] local.INFO: Processing lines: {"lines":[]} 

When I inspect Network in the browser I do not see any requests being made. I don't see any JavaScript errors. I can confirm the rest of my code is working as expected because if I hard code $rawData with URLs the URLs are attached to my model.

0 likes
3 replies
LaryAI's avatar
Level 58

It seems like the issue you're facing is that the data from the textarea is not being sent to the server when the action is triggered. Since you've confirmed that there are no JavaScript errors and no network requests being made, it's possible that the issue lies with how the action is being triggered or how the data is being collected in the frontend.

Here are a few steps you can take to troubleshoot and resolve the issue:

  1. Ensure the Field Name Matches: Double-check that the name you're using to retrieve the field data in the handle method matches the name you've given to the field in the fields method. In your case, it should be 'URLs'.

  2. Check Nova Version: Make sure you are using a version of Nova that supports the showInline() method. If you are using an older version, this method might not be available, and the action might not be triggered correctly.

  3. Inspect the Form Data: When you trigger the action, inspect the network request in your browser's developer tools to ensure that the form data is being sent correctly. Look for the URLs field in the form data of the POST request.

  4. Check JavaScript Console: Even though you mentioned there are no JavaScript errors, it's worth checking the console again when you trigger the action to see if any errors are logged at that moment.

  5. Nova JavaScript Customization: If you have any custom JavaScript for Nova, ensure it's not interfering with the form submission.

  6. Force Form Submission: As a last resort, you can try to force the form submission using JavaScript to ensure that the data is being sent. This is not recommended as a permanent solution but can help you debug the issue.

If none of these steps resolve the issue, you may need to look into creating a custom component for your action that handles the data submission properly.

Here's a basic example of how you might force the form data submission using JavaScript (for debugging purposes only):

document.querySelector('form[action*="your-action-endpoint"]').addEventListener('submit', function(e) {
    e.preventDefault();
    const formData = new FormData(this);
    formData.append('URLs', document.querySelector('textarea[name="URLs"]').value);

    fetch(this.action, {
        method: 'POST',
        body: formData,
        headers: {
            'X-Requested-With': 'XMLHttpRequest',
            // Add any other headers required by your Nova setup
        }
    }).then(response => {
        // Handle the response
    }).catch(error => {
        // Handle any errors
    });
});

Remember to replace 'your-action-endpoint' with the actual endpoint your action is posting to. This code is for debugging purposes and should not be used in production without proper adjustments and testing.

georgetown74's avatar

In the action_events table, in the fields column, I see the following:

a:1:{s:4:"urls";s:23:"https://www.example.com";}

... and this URL is one I used for testing, so the fact that it's showing up in the database suggests there is communication between the front-end and back-end. Any suggestions for why it's still logging as:

[2023-12-26 18:21:27] local.INFO: Raw input data: {"data":null} 
[2023-12-26 18:21:27] local.INFO: Processing lines: {"lines":[]} 
georgetown74's avatar
georgetown74
OP
Best Answer
Level 8

I was able to resolve this by specifying the attribute in my fields method (note the inclusion of 'URLs' a second time in Textarea::make('URLs', 'URLs'):

    public function fields(NovaRequest $request): array
    {
        return [
            Textarea::make('URLs', 'URLs')
                ->rules('required')
                ->help('Paste the sources here, one URL per line.'),
        ];
    }

Please or to participate in this conversation.