The docs show us how to extend certain dropdowns with new options.
See: https://getkirby.com/docs/reference/plugins/extensions/panel-dropdowns#extending-dropdowns
One property available to each option is click
.click
is meant to emit an “event name”, that event should then be handled via an “@action” delegate on the dropdown component.
In most cases where we want to extend existing dropdowns, however, we don’t have access to the <k-dropdown>
component, and also don’t have any opportunity to listen for the emitted event as the original core areas often aren’t listening to it.
This leaves us only with the option to use the dialog
property (which isn’t always the best choice) or extend and rewrite the whole area.
This suggestion proposes a new “event” property for the options, which would trigger the dropdown to broadcast a given event name, and optional payload, on the global $events
bus, allowing any custom component or logic to listen for it.
Proposed API:
return [
[
'text' => 'Greet user',
'icon' => 'user',
'event' => [
'name' => 'greet',
'payload' => $user->name()
]
],
// ...
]
panel.plugin('user/greet', {
created() {
panel.$events.on('greet', (name) =>
window.alert(`Hello ${name}`)
);
}
})
An alternative could be to always broadcast the “event name” of the click
property also on the global bus, maybe namespaced:
"click" => "greet"
emits "dropdown:greet"
or something.
Ideally the API would allow us to specify a payload for the event, however, like exampled above.
At first look, I do like the proposed solution – seems on the one hand okay-ish complex to implement for plugin developers and on the other hand pragmatic and feasible to implement as we don’t have to inject plugin listeners etc.
What seems feasible:
click
is a function, will be called (only works when options get passed in JS)click
is a string: emit to parent as action
event, emit globally as dropdown:
+ the stringclick
is an object: emit global event of subkey name
and pass subkey payload
Wow :)
Didn’t think the team would actually be paying this level of attention to nolt 😅
I thought some more about it after looking at @Nico‘s implementation and I think we should really introduce that third option to pass an object with name and payload, but that third option could then also have an emit key to activate global emission.
The click option would really benefit from being able to add a playoad, but I think it’s better if we don’t automatically combine it with global emission. It feels a bit like too much magic to me. What do you think?
@Bastian i don’t think it needs yet another option. To me it would be totally sufficient, if it shall be limited, to keep the status quo if Click is a string an only if it’s an object do the global emit (the local emit isn’t useful/needed as nobody can listen to that anyways) and add payload.
For me it’s really the same, I think just having the ability to emit global events from the options is nice, no matter how it works if it’s nicely documented. If having a local payload property makes some code easier for the core too, it’s even nicer. ;)
Maybe I wouldn’t call the property “emit” though, I’d rather make it obvious: like 'global' => true
, or 'global' => 'user.greet'
.
If global
is set, do we still emit it to the parent or is it rather: either set name
for emit to parent or global
for global emitted event?
If I’ve understood Bastian correctly…
true
, and name is set: emit “name” globally and locallytrue
, but “name” is not set: throw errorI really like global
as a key here.
I wasn’t thinking that complicated to be honest. I really just thought that emit or global would switch on global emission in addition to local emission.