Sorry, we don't support your browser.  Install a modern browser

"event" property for dropdown options#638

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}`)
    );
  }
})
13 days ago

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.

13 days ago

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.

13 days ago
1

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 string
  • click is an object: emit global event of subkey name and pass subkey payload
12 days ago
Changed the status to
In progress
12 days ago

Wow :)
Didn’t think the team would actually be paying this level of attention to nolt 😅

12 days ago

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?

10 days ago

@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.

10 days ago

I was setting up lab examples and as soon as you start using the k-dropdown-content component or whenever we use the component, it really is the cleaner setup to opt-in to global emission per option.

I’m really coming form a point where I tried to document it in the lab.

10 days ago

I fear you’re too much thinking of this in term of putting Vue code together, while the initial point of this feedback was coming from the dropdowns where developers add their custom option via the backend and the dropdown components aren’t handled by the developers themselves at all.

10 days ago

Ok, different perspective. If we keep the current implementation to simply prefix “dropdown:” as namespace when there’s just a string as click handler and we emit that, we would end up spamming the global event space quite a lot. Suddenly every user, page and file dropdown would all emit “dropdown:delete” But which dropdown just did that? I actually think this could become quite a big problem. That’s why I vote for not automatically emitting global events for the string handlers. But that would make it inconsistent as soon as you pass an object and that object would then suddenly start emitting. Do you know what I mean?

10 days ago

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'.

10 days ago

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?

9 days ago

If I’ve understood Bastian correctly…

  • Whenever “global” is set to a string: emit that string globally
  • Whenever “name” is set: emit to parent
  • When both are set: emit both
  • When none are set: throw error
  • When “global” is set to true, and name is set: emit “name” globally and locally
  • When “global” is set to true, but “name” is not set: throw error
9 days ago

I 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.

9 days ago
Changed the status to
In upcoming releases
7 days ago
1