Statamic add field action : the missing doc, creating a duplicate field action for blocks

It took me quite a while to understand that in order to add action to statamic field, you have to read extending the control panel first. Yes read docs. Did you manage to add your first field action ? for myself I will document here the hards steps that took me to a great feature that allows duplicating an existing replicator block content to a new entry, in the context of using a page builder based on replicator fieldset. The page builder itself -and its frontend templates - initially comes from the blogo starter kit, which is quickly extended with my own sets.

Some issues left

I tested this duplicator action guy with a few content types and it works fine, I have identified a few possible evolution paths

  • duplicator bugs on images, saves an extra string in the asset field, for the moment I remove them manually in the md file
  • would like to duplicate the set to any possible entry type, including to a global set
  • might have issues with duplicates unique id ??

the principle : field action for replicator sets, linked to php controller

Field action javascript : wave-field-actions.js

Statamic.$fieldActions.add('replicator-fieldtype-set', {
 title: 'WAVE Generate Content',
 confirm: {
 fields: {
 name: {
 type: "text",
 display: 'Name',
 instructions: 'Enter your new page title',
 validate: ['required', 'min:2']
 }
 }
 },
 // visible: ({ config }) => config.handle === 'text_block',
 run: async ({ values, confirmation}) => {
 console.log(values)
 try {
 const response = Statamic.$request.post('/wave-api/entries', {
 collection: 'pages',

 title: confirmation.values.name,
 content: values

 });

 Statamic.$toast.success('Entry created successfully');

 } catch (error) {
 console.error('Error creating entry:', error);
 Statamic.$toast.error('Failed to create entry');
 }
 }

});

as you can see in the code above, the result of the action is to post the data to a controller I've created, accessible by the web route :

Route::post('/wave-api/entries', [WaveController::class, 'store'])->middleware(['web']);

The controller that creates the new entry


use Illuminate\Http\Request;
use Statamic\Facades\Entry;

class WaveController extends Controller
{
public function store(Request $request)
{

    $mappedContent =  $request->content;
//    $mappedContent["_id"] =    Str::uuid()->toString();;

$entry = Entry::make()
->collection($request->collection)
    ->blueprint('page')
->data([
'title' => $request->title,

"blocks"=>[$mappedContent]
]);
print_r($mappedContent);
$entry->save();

return response()->json(['success' => true]);
}
}

Going further with duplicate to existing entry

here is a new version of the field action with a new confirmation field : select an entry and the block will be duplicated to that entry

Statamic.$fieldActions.add('replicator-fieldtype-set', {
    title: 'WAVE Duplicate  Content',
    confirm: {
        text: 'Duplicate this content to new page or existing page',
        fields: {
            name: {
                type: "text",
                display: 'Name',
                instructions: 'Enter your new page title',
                validate: [  'min:2']
            },
            target_page: {
                type: "entries",
                display: 'OR Select Target Page',
                instructions: 'Choose an existing page to update',
                max_items: 1,
                collections: ['pages']
            }
        }
    },
    // visible: ({ config }) => config.handle === 'text_block',
    run:  async ({  values, confirmation}) => {
        // console.log(values)
        try {
            // alert (confirmation.values.target_page)
            const response =   Statamic.$request.post('/wave-api/entries', {
                collection: 'pages',

                    title: confirmation.values.name,
                target_page:confirmation.values.target_page,
                    content: values

            });
        if (confirmation.values.target_page.length==1)
            Statamic.$toast.success('Entry updated successfully');
else
            Statamic.$toast.success('Entry created successfully');

        } catch (error) {
            console.error('Error creating entry:', error);
            Statamic.$toast.error('Failed to create entry');
        }
    }



});


//https://jacksleight.dev/posts/adding-actions-to-specific-statamic-fields
//https://maciekpalmowski.dev/blog/field-actions-in-statamic-are-amazing/

the controller side :

<?php
// app/Http/Controllers/EntryController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Statamic\Facades\Entry;

class WaveController extends Controller
{
public function store(Request $request)
{

    $mappedContent =  $request->content;
//    $mappedContent["_id"] =    Str::uuid()->toString();;
if ($request->target_page)
{
    $selectedPageId = $request->target_page[0];
    $entry = Entry::find($selectedPageId);
    if (!$entry) {
        return response()->json(['success' => false, 'message' => 'Entry not found'], 404);
    }
    $currentBlocks = $entry->get('blocks') ?? [];

    // Add new block to existing blocks
    $newBlocks = array_merge($currentBlocks, [$mappedContent]);

    // Update the entry
    $entry->set('blocks' , $newBlocks);
    $entry->save();


}
    else {
        $entry = Entry::make()
            ->collection($request->collection)
            ->blueprint('page')
            ->data([
                'title' => $request->title,

                "blocks" => [$mappedContent]
            ]);

        $entry->save();
    }

return response()->json(['success' => true]);
}
}

Leave a Comment

Your email address will not be published. Required fields are marked *

To top