cms icon indicating copy to clipboard operation
cms copied to clipboard

[5.x] Add a `creating-entry` hook to allow default values to be set

Open ryanmitchell opened this issue 2 years ago • 11 comments

This PR fires a creating-entry hook on the 'create' screen of the CP, allowing you to programatically set default values for fields.

You can see this has been asked for in a few places, e.g. https://github.com/statamic/ideas/issues/964, https://discord.com/channels/489818810157891584/489818810157891586/1146021950112665682

You can then add a listener like follows:

EntriesController::hook('creating-entry', function ($entry) {
  $entry->set('title', 'This value was set in the listener');
});

Which lets you modify the default values: Screenshot 2023-08-29 at 13 53 14

Obviously titles can have their default values in other ways, but where this becomes really useful is when you want to have default replicator or grid values.

ryanmitchell avatar Aug 29 '23 12:08 ryanmitchell

That was what I tried to do originally, but the event fires without the entry parameter being set. I think maybe from the Entry policy?

ryanmitchell avatar Sep 05 '23 21:09 ryanmitchell

Oh yeah there's code in there to intentionally not fire the event. Bah.

jasonvarga avatar Sep 05 '23 22:09 jasonvarga

Any chance this PR or a solution for this topic (pre-filling of fields, replicator fields in our case, based on blueprints) will be part of the core?

Currently we apply this PR as an patch to our code base after every cms update. This approach is currently working for us, but It feels like an hack.

Thanks again @ryanmitchell for this PR and solution!

radermacher avatar Sep 26 '23 10:09 radermacher

In it's current state, I don't think it'll get merged. But I'm leaving this open temporarily as a reminder to think about a permanent solution.

jasonvarga avatar Sep 28 '23 14:09 jasonvarga

You can achieve almost the same thing by applying a default value to your replicator field in the blueprint... eg.

          -
            handle: replicator_field
            field:
              collapse: false
              previews: true
              fullscreen: true
              sets:
                new_set_group:
                  display: 'New Set Group'
                  instructions: null
                  icon: null
                  sets:
                    test_set_1:
                      display: 'Test set 1'
                      instructions: null
                      icon: null
                      fields:
                        -
                          handle: title
                          field:
                            input_type: text
                            antlers: false
                            type: text
                            display: Title
                            icon: text
                            localizable: false
                            listable: hidden
                            instructions_position: above
                            visibility: visible
                            hide_display: false
                    test_set_2:
                      display: 'Test set 2'
                      instructions: null
                      icon: null
                      fields:
                        -
                          handle: title
                          field:
                            input_type: text
                            antlers: false
                            type: text
                            display: Title
                            icon: text
                            localizable: false
                            listable: hidden
                            instructions_position: above
                            visibility: visible
                            hide_display: false
                    replicator_in_replicator:
                      display: 'Replicator in replicator'
                      instructions: null
                      icon: null
                      fields:
                        -
                          handle: replicator_field
                          field:
                            collapse: false
                            previews: true
                            fullscreen: true
                            sets:
                              new_set_group:
                                display: 'New Set Group'
                                instructions: null
                                icon: null
                                sets:
                                  new_set:
                                    display: 'New Set'
                                    instructions: null
                                    icon: null
                                    fields:
                                      -
                                        handle: text
                                        field:
                                          input_type: text
                                          antlers: false
                                          type: text
                                          display: Text
                                          icon: text
                                          localizable: false
                                          listable: hidden
                                          instructions_position: above
                                          visibility: visible
                                          hide_display: false
                            type: replicator
                            display: 'Replicator Field'
                            icon: replicator
                            localizable: false
                            listable: hidden
                            instructions_position: above
                            visibility: visible
                            hide_display: false
              type: replicator
              display: 'Replicator Field'
              icon: replicator
              localizable: false
              listable: hidden
              instructions_position: above
              visibility: visible
              hide_display: false
              default:
                -
                  id: lkhwp0kp
                  title: Ryan
                  type: test_set_1
                  enabled: true
                -
                  id: lki12mr5
                  replicator_field:
                    -
                      id: lki12nxn
                      text: text
                      type: new_set
                      enabled: true
                  type: replicator_in_replicator
                  enabled: true

Obviously the event lets you apply use non-fixed values, eg if you were pulling from an API. So it would be good to come up with a solution that allows for that.

ryanmitchell avatar Sep 29 '23 05:09 ryanmitchell

Thanks @ryanmitchell 🙏 Your solution works like in your example. Sadly it doesn't work with imported replicator fields, which we use to prevent duplicated field configs in blueprints. Default values could be set in the shared fieldset but couldn't be set/overwritten per blueprint. We need the latter.

So we hope @jasonvarga and team find a mergeable solution. Until then, we will work with an applied patch after every Statamic update 😬

radermacher avatar Oct 05 '23 10:10 radermacher

Until then, we will work with an applied patch after every Statamic update 😬

You can use a composer patch to automate it.

jasonvarga avatar Oct 05 '23 14:10 jasonvarga

Until then, we will work with an applied patch after every Statamic update 😬

You can use a composer patch to automate it.

Awesome! Thank you @jasonvarga, I didn't know about this solution to apply patches!

radermacher avatar Oct 05 '23 14:10 radermacher

What about using a hook for this? You could pass the blank entry to it and let it be amended?

ryanmitchell avatar Sep 11 '24 16:09 ryanmitchell

@jasonvarga I've updated this to use a hook instead of an event. Does this sit any better with you?

ryanmitchell avatar Oct 08 '24 12:10 ryanmitchell

Just chiming in to say that this works great in its current state. Wouldn't mind to see it merged :) We're using it to define a random seed that needs to be present on first save.

// app/Providers/AppServiceProvider.php

EntriesController::hook('creating-entry', function ($entry) {
  $entry->set('rand', random_int(1, 9999));
});

daun avatar Apr 07 '25 10:04 daun

Now that you're allowing url params since https://github.com/statamic/cms/pull/12699 it would seem to make sense to add this hook? I can update to target master if that works for you?

ryanmitchell avatar Nov 03 '25 10:11 ryanmitchell

Oh yeah good call!

jasonvarga avatar Nov 03 '25 14:11 jasonvarga

@jasonvarga should be you now.

ryanmitchell avatar Nov 03 '25 16:11 ryanmitchell

Amazing, thank you.

For anyone following along, the payload format has changed a little, so you now want to do something like:

EntriesController::hook('creating-entry', function ($payload, $next) {
    $payload->values = [...$payload->values, 'title' => 'testing 123'];

    return $next($payload);
});

ryanmitchell avatar Nov 04 '25 07:11 ryanmitchell