stimulus-rails-helpers 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/LICENSE +21 -0
- data/README.md +257 -0
- data/stimulus-rails-helpers.gemspec +2 -2
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5d94e7182dccf2637dc640562e39d84921aa1de182dc622486a64f6a582e82a0
|
|
4
|
+
data.tar.gz: e9181e3deed0534406dec25caf8920cdf8fb312d39e59a67a252832e7e680686
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4b23329bf97c705a7fa254d85b91b6c26565884a23df9b1ee9441f4ffba1b638d32b8e09a2ce5b70e45d84c092e1933885594418b2191739d5e3ae5f841370fd
|
|
7
|
+
data.tar.gz: c6d195bdf2f4964b6a04ddda64f22343550499e14d17f3dadb083285cc7a224019f8fe8933a89fa3fefc6647d20fd8bed568749b7c58b32af3eaa12a4c085b13
|
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jon Gilbraith
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# Rails Helpers for Stimulus
|
|
2
|
+
|
|
3
|
+
Some helpers to help tame the task of wrangling Stimulus' `data` attributes.
|
|
4
|
+
|
|
5
|
+
At its core it revolves around a simple short hand notation for describing the various attributes you have to generate when wiring Stimulus controllers into the DOM.
|
|
6
|
+
|
|
7
|
+
Design philosophy:
|
|
8
|
+
|
|
9
|
+
* Just use camel case
|
|
10
|
+
* Just use symbols (well almost, for all the Stimulus parts at least)
|
|
11
|
+
* Leverage hashes to describe Stimulus attributes in an intuitive, terser format
|
|
12
|
+
|
|
13
|
+
No validation or sanity checking, it's purely a shorthand. It won't warn you if you've got a typo in an attribute or anything like that. But hopefully this makes it easier to avoid these kinds of issues.
|
|
14
|
+
|
|
15
|
+
## How it works
|
|
16
|
+
|
|
17
|
+
Two core methods for Stimulus attributes, with one more for namespaces, then two more that are identical counterparts for the first two, just for when using namespaces.
|
|
18
|
+
|
|
19
|
+
## The two methods - create an element or generate data attributes, for adding to another element
|
|
20
|
+
|
|
21
|
+
Create an element with the helper `stimulus_element` (or `stim_el` for short). Pass a block if you have content to go inside the element. Much like `content_tag` (that's what's used underneath).
|
|
22
|
+
|
|
23
|
+
Generate attributes with the helper `stimulus_data` (or `stim_data` for short).
|
|
24
|
+
|
|
25
|
+
Both of these use pretty much the same arguments, other than the fact that `stimulus_element` has an optional first argument of what type of element it is (it defaults to `:div`) and it can take a block.
|
|
26
|
+
|
|
27
|
+
When using the namespace functionality (documented at the end of this README) you yield an object on which you call two methods that are the direct equivalent of these two methods.
|
|
28
|
+
|
|
29
|
+
## Example
|
|
30
|
+
|
|
31
|
+
Simple example of a Stimulus controller declared on a wrapper div, that watches a field via the `refreshCount` action and updates a message in a div with target of `field`
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
<%= stimulus_element controller: :word_count, class: "form-group" do %>
|
|
35
|
+
<%=
|
|
36
|
+
text_field_tag :user_name,
|
|
37
|
+
params[:user_name],
|
|
38
|
+
data: stimulus_data(actions: { word_count: :refresh_count }),
|
|
39
|
+
class: "input text-field"
|
|
40
|
+
%>
|
|
41
|
+
<%= stimulus_element targets: { word_count: :field }, class: "word-count-message" %>
|
|
42
|
+
<% end %>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This will produce something along the lines of:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
<div data-controller"word-count" class="form-group">
|
|
49
|
+
<input type="text" name="user_name" value="jon" data-action="word-count#refreshCount" class="input text-field">
|
|
50
|
+
<div data-word-count-target="field" class="word-count-message"></div>
|
|
51
|
+
</div>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
That's all there is to it. You just need to know what other arguments you can pass to `stimulus_element` and `stimulus_data` to handle other types of Stimulus attributes.
|
|
55
|
+
|
|
56
|
+
## The arguents in depth
|
|
57
|
+
|
|
58
|
+
### `controllers`
|
|
59
|
+
|
|
60
|
+
Pass in an array of controller names and you'll get the `data-controller` attribute with the arguments provided.
|
|
61
|
+
|
|
62
|
+
So for example `controllers: [:word_count, :image_upload]` gets you:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
data-controller="word-count image-upload"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### `targets`
|
|
69
|
+
|
|
70
|
+
Pass in a correctly structured hash and you get the expected data attributes for the targets.
|
|
71
|
+
|
|
72
|
+
The format is `controller_name: :target_name` for a single target, or `controller_name: [:target_name, :another_target_name]`
|
|
73
|
+
|
|
74
|
+
So for example:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
targets: {
|
|
78
|
+
calculate_tax: :tax_amount,
|
|
79
|
+
calculate_total: [:sub_total, :grand_total]
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Gets you:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
data-calculate-tax-target="taxAmount"
|
|
87
|
+
data-calculate-total-target="subTotal"
|
|
88
|
+
data-calculate-total-target="grandTotal"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### `actions`
|
|
92
|
+
|
|
93
|
+
Pass in a correctly structured hash (for multiple actions for multiple controllers) and you get the expected data attribute for the actions.
|
|
94
|
+
|
|
95
|
+
The format is `controller_name: :action_name` for the default event, or `controller_name: { event: :action_name }` for other events.
|
|
96
|
+
|
|
97
|
+
So for example:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
actions: {
|
|
101
|
+
calculate_tax: :refresh_total,
|
|
102
|
+
calculate_total: { blur: :warn_if_exceeds_balance }
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Gets you:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
data-action="calculate-tax#refreshTotal blur->calculate-total#warnIfExceedsBalance"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `values`
|
|
113
|
+
|
|
114
|
+
Pass in a correctly structured hash and you get the expected data attributes for the values.
|
|
115
|
+
|
|
116
|
+
The format is `controller_name: { value_name: :value_value }`
|
|
117
|
+
|
|
118
|
+
So for example: `values: { calculate_tax: { tax_rate: 20 } }`
|
|
119
|
+
|
|
120
|
+
Gets you:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
data-calculate-tax-tax-rate-value="20"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `outlets`
|
|
127
|
+
|
|
128
|
+
Pass in a correctly structured hash and you get the expected data attributes for the outlets.
|
|
129
|
+
|
|
130
|
+
The format is `source_controller_name: { target_controller_name: :target_controller_selector }`
|
|
131
|
+
|
|
132
|
+
So for example:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
outlets: {
|
|
136
|
+
calculate_tax: {
|
|
137
|
+
calculate_total: "#calculate-total"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Gets you:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
data-calculate-tax-calculate-total-outlet="#calculate-total"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
# Additional attributes
|
|
149
|
+
|
|
150
|
+
In both methods, any additional arguments passed in will be passed on as other attributes (`stimulus_element`) or other data attributes (`stimulus_data`).
|
|
151
|
+
|
|
152
|
+
E.g.
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
stimulus_element(:span, targets: { calculate_tax: :tax_amount }, class: "highlight")
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Gets you:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
<span data-calculate-tax-target="taxAmount" class="highlight"></span>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Or
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
<%=
|
|
168
|
+
text_field_tag :user_name,
|
|
169
|
+
params[:user_name],
|
|
170
|
+
data: stimulus_data(
|
|
171
|
+
actions: { word_count: :refresh_count },
|
|
172
|
+
user_tracking_id: 1234
|
|
173
|
+
),
|
|
174
|
+
class: "input text-field"
|
|
175
|
+
%>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
<input type="text" name="user_name" value="jon" data-action="word-count#refreshCount" data-user-tracking-id="1234" class="input text-field">
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
# Namespaces
|
|
183
|
+
|
|
184
|
+
The quick and dirty way if applying a namespace is to just pass a `namespace` param when calling `stimulus_element` or `stimulus_data`. However in most scenarios that will likely get repetetive.
|
|
185
|
+
|
|
186
|
+
To declare your namespace once and have it apply automatically you can use a namespace scope.
|
|
187
|
+
|
|
188
|
+
## Namespace scopes
|
|
189
|
+
|
|
190
|
+
You can call the `stimulus_namespace` helper (or `stim_ns` for short) with a any number of arguments and it will yield an object for each of them, each representing a separate namespace.
|
|
191
|
+
|
|
192
|
+
On the yielded object(s) you call `element` (or `el` for short) or `data` (short enough, no alias) on them and they work exactly the same way as the helpers described before, except all outputs will have the prefix attached.
|
|
193
|
+
|
|
194
|
+
Like so:
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
<%= stimulus_namespace :admin do |stimulus| %>
|
|
198
|
+
<%= stimulus.element controller: :word_count do %>
|
|
199
|
+
text_field_tag :user_name,
|
|
200
|
+
params[:user_name],
|
|
201
|
+
data: stimulus.data(actions: { word_count: :refresh_count }),
|
|
202
|
+
class: "input text-field"
|
|
203
|
+
%>
|
|
204
|
+
<%= stimulus_element targets: { word_count: :field }, class: "word-count-message" %>
|
|
205
|
+
<% end %>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
This will produce something along the lines of:
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
<div data-controller"admin--word-count" class="form-group">
|
|
212
|
+
<input type="text" name="user_name" value="jon" data-action="admin--word-count#refreshCount class="input text-field">
|
|
213
|
+
<div data-admin--word-count-target="field" class="word-count-message"></div>
|
|
214
|
+
</div>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
With multiple namespaces:
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
<%= stimulus_namespace :one_namespace, :another_namespace do |one, another| %>
|
|
221
|
+
.
|
|
222
|
+
.
|
|
223
|
+
.
|
|
224
|
+
<% end %>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
And you can describe deeper nested namespaces too:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
<%= stimulus_namespace parent: :child do |stimulus| %>
|
|
231
|
+
.
|
|
232
|
+
.
|
|
233
|
+
.
|
|
234
|
+
<% end %>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Which will apply a prefix of `parent--child--`.
|
|
238
|
+
|
|
239
|
+
Finally, arrays work too:
|
|
240
|
+
|
|
241
|
+
```
|
|
242
|
+
<%= stimulus_namespace [:first, :second, :third] do |stimulus| %>
|
|
243
|
+
.
|
|
244
|
+
.
|
|
245
|
+
.
|
|
246
|
+
<% end %>
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Which produces `first--second--third--`.
|
|
250
|
+
|
|
251
|
+
# Problems
|
|
252
|
+
|
|
253
|
+
It's occurred to me that if you have overlapping namespaces you'll likely want to populate attributes for both of them on the same element, and my current approach doesn't take that into account.
|
|
254
|
+
|
|
255
|
+
You'd have to call `stimulus_data` and merge the output of that into other calls of `stimulus_element` and `stimulus_data`, which on second thoughts might not be so janky after all.
|
|
256
|
+
|
|
257
|
+
But I'll be thinking about a good solution for that.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
s.name = "stimulus-rails-helpers"
|
|
3
|
-
s.version = "0.1.
|
|
3
|
+
s.version = "0.1.2"
|
|
4
4
|
s.summary = "Some helpers to help tame the task of wrangling Stimulus' data attributes."
|
|
5
5
|
s.authors = ["Jon Gilbraith"]
|
|
6
|
-
s.files = ["stimulus-rails-helpers.gemspec"] + Dir["lib/**/*.rb"]
|
|
6
|
+
s.files = ["stimulus-rails-helpers.gemspec", "README.md", "CHANGELOG.md", "LICENSE"] + Dir["lib/**/*.rb"]
|
|
7
7
|
s.metadata = { "source_code_uri" => "https://github.com/jongilbraith/stimulus-rails-helpers" }
|
|
8
8
|
s.license = "MIT"
|
|
9
9
|
s.homepage = "https://github.com/jongilbraith/stimulus-rails-helpers"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stimulus-rails-helpers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jon Gilbraith
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-06-
|
|
11
|
+
date: 2026-06-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: actionview
|
|
@@ -44,6 +44,9 @@ executables: []
|
|
|
44
44
|
extensions: []
|
|
45
45
|
extra_rdoc_files: []
|
|
46
46
|
files:
|
|
47
|
+
- CHANGELOG.md
|
|
48
|
+
- LICENSE
|
|
49
|
+
- README.md
|
|
47
50
|
- lib/stimulus-rails-helpers.rb
|
|
48
51
|
- lib/stimulus_rails_helpers/rails_helpers.rb
|
|
49
52
|
- lib/stimulus_rails_helpers/railtie.rb
|