selfawarestudio/picoapp

Subscribing to external events when multiple instances of a component

lmartins opened this issue · 5 comments

Hi, this is a pretty neat and useful library, thank you for sharing!

I have a quick question though, how would you typically approach a situation where you have multiple instances of a component type, and you want to subscribe to a command from a different component.

Practical example. Lets say your app has multiple Drawer components, and you have external component that can control the state of those drawer. In this example, we would need a button component to emit an event in such a way that only the target drawer would react to.

I though about passing an identifier as the event payload, but that adds to the state I wonder if there's a cleaner way to achieve this.

Thank you!

@lmartins hey! Sorry for the delay, must have missed this notification.

I guess I've always avoided that issue by abstracting the shared functionality into a utility that could be reused between discrete components i.e. drawerOne drawerTwo etc. Each could listen for its own property then, but trigger the same classnames using the shared utility to open/close itself.

Another way I've approached similar problems is to toss another data attribute on the element and use that as the identifier for the component. I've never done it like this, but it should work:

<div data-component="drawer" data-prop="drawerOne"></div>
export default component((node, ctx) => {
  const prop = node.getAttribute('data-prop') // or node.dataset.prop

  ctx.on(prop, state => {}) // handle this drawer here
})

Hope that's helpful!

Hey @estrattonbailey no worries, thank you for getting back to me with your suggestion. I had gone with the identifier approach as you suggested as it works pretty good. Thank you for confirming that, and thank you for your work on this useful library!

Hey @estrattonbailey - sorry to comment on a closed issue, but running into this same problem with nav drawers specifically. Had the idea of the data-prop approach, but could use a bit more context on what exactly is meant to be happening in

ctx.on(prop, state => {//this part here})

Let's say you've got a navDrawer.js component, presumably you're adding and removing classes within that section, but I'm at a bit of a loss for what's actually causing any of that interior code to fire.

Does ctx.on(prop, state => {} just listen for any changes to the element defined by prop? If so, what does picoapp consider to be a change?

@aeblin my understanding is that ctx is just a pub/sub handler, so that you can have communication between components. This means that when a component publishes an event, all the subscribers can be notified of that message. So it's not like picoapp is doing anything fancy watching for changes on the DOM, the only think the library does is to have a way for you to quickly register and run components via the data-attribute, passing state and the pub/sub handler to those component so you can then subscribe to events.

@aeblin great question! Thanks @lmartins for the explainer.

Yeah it's just pub/sub, but I've probably make it unnecessarily confusing by calling it ctx (context) and not explaining what that is. Internally it uses evx, which might help shed some light. Basically, the context object is a way to access state, and subscribe to state updates.

Event emissions and state updates cause that code to fire, depending on what event/state property you've subscribed to.

Hope that helps!

P.S. for className updates, this might be helpful to you: https://github.com/estrattonbailey/dcx