Lots of Actions


#1

I’m working on a controller that’s going to be used with Active Storage Direct Upload.

Active Storage has a lot of events that I’d like to handle on my Stimulus controller. If I add them all to the form, it looks really messy.

I’ve already added this to my form:

data: { controller: 'backblaze', action:  'direct-upload:initialize@window->backblaze#initializeDownload direct-upload:before-blob-request@window->backblaze#beforeBlobRequest direct-upload:before-storage-request@window->backblaze#beforeStorageRequest direct-upload:error@window->backblaze#error keypress@window->backblaze#preventForm' } 

and it’s only going to get messier.

Is there a rule of thumb for when to move all the actions from data-target in the html to adding listeners in the controller’s connect() function?


#2

You can add listeners in your controller’s connect():

   connect() {
    const target = ..
    target.addEventListener('event1',  this.action1)
    target.addEventListener('event2',  this.action2)
    ..
   }

#3

I tried writing it like this, which would be a lot nicer in Rails

data: {
        controller: 'backblaze',
        action: 'direct-upload:initialize@window->backblaze#initializeDownload',
        action: 'direct-upload:before-blob-request@window->backblaze#beforeBlobRequest',
        action: 'direct-upload:before-storage-request@window->backblaze#beforeStorageRequest',
        action: 'direct-upload:error@window->backblaze#error', 
        action: 'keypress@window->backblaze#preventForm'
      }

but it doesn’t work… only the last action makes it to the html :slightly_frowning_face:

So probably the nicer solution would be to define an array of actions

actions = [
      "direct-upload:initialize@window->backblaze#initializeDownload",
      "direct-upload:before-blob-request@window->backblaze#beforeBlobRequest",
      "direct-upload:before-storage-request@window->backblaze#beforeStorageRequest",
      "direct-upload:error@window->backblaze#error",
      "keypress@window->backblaze#preventForm"
    ]

and then just join this array in your form definition

data: {
        controller: "backblaze",
        action: actions.join(" ")
      }

#4

Rule of thumb: When you add all those very same actions again when you use the controller again, then you might as well move them into the controller