Suggestions for linking buttons to a textarea

Coming from an Angular background, I am used to having a Controller manage an entire form. I understand that with Stimulus, we want to keep our Stimulus classes small and focused. As such, I’m still learning how to translate my Angular mindset into a Hotwire context.

Consider this: I have a <textarea> and below it I have a bunch of buttons that represent emoji characters. Something like this:

<form>
	<textarea></textarea>
	<div class="emoji">
		<button data-hex="...">:)</button>
		<button data-hex="...">:|</button>
		<button data-hex="...">:(</button>
	</div>
</form>

When the user clicks on one of the buttons, my code needs to take the data-hex attribute, convert the “code points” into a Unicode character (String.fromCodePoint()), and then insert the generated emoji into the <textarea> at the current .selectionEnd location.

I’m not sure how to best go about this. In a non-Stimulus context, all of this logic exists in the “Form controller”. Obviously not good for reusability.

Some ideas:

  • Add a data-controller to the form and then just manage everything at the root location. This is basically what I am doing right now in order to port my old code into Stimulus context.

  • Add a button-based controller. Basically, add a data-controller to each emoji button. This controller could then listen for the click-event and .dispatch() a custom event like emoji:insert (including the generated Emoji Unicode in the event detail). Of course, then I’d have to have something else higher-up in the DOM to listen for those events and translate them into a <textarea> mutation.

  • Add a button-based controller; but, this time, use an outlet to have the button-controller talk to the ?textarea controller? or ?form controller? and call some method like formOutlet.insertEmoji( string ).

In the above, I’m adding a controller to each button. However, I suppose I could just have a controller on the div.emoji container and use either event delegation or wire-up “targets”.

Anyway, I just don’t yet have a good sense of what the “Stimulus Way” is for something like this. Would love any suggestions.

Small controllers that do one thing and one thing well is a good guideline, but it’s fine to deviate from it if you feel the guideline is holding you back.

Personally I think this might be a case where a controller on the form element and targets/actions on child nodes might be better. Outlets would work if you want to keep controllers atomic, but not sure you gain much in this particular instance.

So yeah, I would just put a data-action on each button and a target on the textarea.

1 Like

Thanks for the feedback. It’s hard to know where the line is until you build a bunch of stuff this way. I won’t stress over it too much. Having a controller on the form will also be helpful because I’ll want other things (like CMD+Enter on the <textarea> to submit the form).