Skip to content

Commit f36a095

Browse files
committed
More work on data-event to use action params
1 parent 559594a commit f36a095

File tree

6 files changed

+27
-89
lines changed

6 files changed

+27
-89
lines changed

src/LiveComponent/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
+ data-live-action-param="save"
4141
>Save</button>
4242
```
43+
- [BC BREAK] The `data-event` attribute was removed in favor of using Stimulus
44+
"action parameters": rename `data-event` to `data-live-event-param`. Additionally,
45+
if you were passing arguments to the event name, use action parameter attributes
46+
for those as well - e.g. `data-live-foo-param="bar"`.
4347
- Add support for URL binding in `LiveProp`
4448
- Allow multiple `LiveListener` attributes on a single method.
4549
- Requests to LiveComponent are sent as POST by default

src/LiveComponent/assets/src/live_controller.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -227,31 +227,33 @@ export default class LiveControllerDefault extends Controller<HTMLElement> imple
227227
return this.component.render();
228228
}
229229

230-
emit(event: Event) {
230+
emit(event: any) {
231231
this.getEmitDirectives(event).forEach(({ name, data, nameMatch }) => {
232232
this.component.emit(name, data, nameMatch);
233233
});
234234
}
235235

236-
emitUp(event: Event) {
236+
emitUp(event: any) {
237237
this.getEmitDirectives(event).forEach(({ name, data, nameMatch }) => {
238238
this.component.emitUp(name, data, nameMatch);
239239
});
240240
}
241241

242-
emitSelf(event: Event) {
242+
emitSelf(event: any) {
243243
this.getEmitDirectives(event).forEach(({ name, data }) => {
244244
this.component.emitSelf(name, data);
245245
});
246246
}
247247

248-
private getEmitDirectives(event: Event): Array<{ name: string; data: any; nameMatch: string | null }> {
249-
const element = event.currentTarget as HTMLElement;
250-
if (!element.dataset.event) {
251-
throw new Error(`No data-event attribute found on element: ${getElementAsTagText(element)}`);
248+
private getEmitDirectives(event: any): Array<{ name: string; data: any; nameMatch: string | null }> {
249+
const params = event.params;
250+
if (!params.action) {
251+
throw new Error(`No event name provided on element: ${getElementAsTagText(event.currentTarget)}. Did you forget to add the "data-live-event-param" attribute?`);
252252
}
253-
254-
const eventInfo = element.dataset.event;
253+
const eventInfo = params.event;
254+
// all other params are considered event arguments
255+
const eventArgs = { ...params };
256+
delete eventArgs.event;
255257

256258
// data-event="name(product_list)|some_event"
257259
const directives = parseDirectives(eventInfo);
@@ -270,7 +272,7 @@ export default class LiveControllerDefault extends Controller<HTMLElement> imple
270272

271273
emits.push({
272274
name: directive.action,
273-
data: directive.named,
275+
data: eventArgs,
274276
nameMatch,
275277
});
276278
});

src/LiveComponent/assets/test/Directive/directives_parser.test.ts

Lines changed: 1 addition & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ describe('directives parser', () => {
2929
assertDirectiveEquals(directives[0], {
3030
action: 'hide',
3131
args: [],
32-
named: {},
3332
modifiers: [],
3433
})
3534
});
@@ -40,7 +39,6 @@ describe('directives parser', () => {
4039
assertDirectiveEquals(directives[0], {
4140
action: 'addClass',
4241
args: ['opacity-50'],
43-
named: {},
4442
modifiers: [],
4543
})
4644
});
@@ -51,7 +49,6 @@ describe('directives parser', () => {
5149
assertDirectiveEquals(directives[0], {
5250
action: 'addClass',
5351
args: ['opacity-50 disabled'],
54-
named: {},
5552
modifiers: [],
5653
})
5754
});
@@ -63,7 +60,6 @@ describe('directives parser', () => {
6360
action: 'addClass',
6461
// space between arguments is trimmed
6562
args: ['opacity-50', 'disabled'],
66-
named: {},
6763
modifiers: [],
6864
})
6965
});
@@ -74,13 +70,11 @@ describe('directives parser', () => {
7470
assertDirectiveEquals(directives[0], {
7571
action: 'addClass',
7672
args: ['opacity-50'],
77-
named: {},
7873
modifiers: [],
7974
})
8075
assertDirectiveEquals(directives[1], {
8176
action: 'addAttribute',
8277
args: ['disabled'],
83-
named: {},
8478
modifiers: [],
8579
})
8680
});
@@ -91,63 +85,16 @@ describe('directives parser', () => {
9185
assertDirectiveEquals(directives[0], {
9286
action: 'hide',
9387
args: [],
94-
named: {},
9588
modifiers: [],
9689
})
9790
assertDirectiveEquals(directives[1], {
9891
action: 'addClass',
9992
args: ['opacity-50 disabled'],
100-
named: {},
10193
modifiers: [],
10294
})
10395
assertDirectiveEquals(directives[2], {
10496
action: 'addAttribute',
10597
args: ['disabled'],
106-
named: {},
107-
modifiers: [],
108-
})
109-
});
110-
111-
it('parses single named argument', () => {
112-
const directives = parseDirectives('save(foo=bar)');
113-
expect(directives).toHaveLength(1);
114-
assertDirectiveEquals(directives[0], {
115-
action: 'save',
116-
args: [],
117-
named: { foo: 'bar' },
118-
modifiers: [],
119-
})
120-
});
121-
122-
it('parses multiple named arguments', () => {
123-
const directives = parseDirectives('save(foo=bar, baz=bazzles)');
124-
expect(directives).toHaveLength(1);
125-
assertDirectiveEquals(directives[0], {
126-
action: 'save',
127-
args: [],
128-
named: { foo: 'bar', baz: 'bazzles' },
129-
modifiers: [],
130-
})
131-
});
132-
133-
it('parses arguments and spaces are kept', () => {
134-
const directives = parseDirectives('save(foo= bar)');
135-
expect(directives).toHaveLength(1);
136-
assertDirectiveEquals(directives[0], {
137-
action: 'save',
138-
args: [],
139-
named: { foo: ' bar' },
140-
modifiers: [],
141-
})
142-
});
143-
144-
it('parses argument names with space is trimmed', () => {
145-
const directives = parseDirectives('save(foo =bar)');
146-
expect(directives).toHaveLength(1);
147-
assertDirectiveEquals(directives[0], {
148-
action: 'save',
149-
args: [],
150-
named: { foo: 'bar' },
15198
modifiers: [],
15299
})
153100
});
@@ -158,7 +105,6 @@ describe('directives parser', () => {
158105
assertDirectiveEquals(directives[0], {
159106
action: 'addClass',
160107
args: ['disabled'],
161-
named: {},
162108
modifiers: [
163109
{ name: 'delay', value: null }
164110
],
@@ -171,20 +117,18 @@ describe('directives parser', () => {
171117
assertDirectiveEquals(directives[0], {
172118
action: 'addClass',
173119
args: ['disabled'],
174-
named: {},
175120
modifiers: [
176121
{ name: 'delay', value: '400' },
177122
],
178123
})
179124
});
180125

181126
it('parses multiple modifiers', () => {
182-
const directives = parseDirectives('prevent|debounce(400)|save(foo=bar)');
127+
const directives = parseDirectives('prevent|debounce(400)|save');
183128
expect(directives).toHaveLength(1);
184129
assertDirectiveEquals(directives[0], {
185130
action: 'save',
186131
args: [],
187-
named: { foo: 'bar' },
188132
modifiers: [
189133
{ name: 'prevent', value: null },
190134
{ name: 'debounce', value: '400' },
@@ -211,22 +155,10 @@ describe('directives parser', () => {
211155
}).toThrow('Missing space after addClass()')
212156
});
213157

214-
it('named and unnamed arguments cannot be mixed', () => {
215-
expect(() => {
216-
parseDirectives('save(foo=bar, baz)');
217-
}).toThrow('Normal and named arguments cannot be mixed inside "save()"')
218-
});
219-
220158
it('modifier cannot have multiple arguments', () => {
221159
expect(() => {
222160
parseDirectives('debounce(10, 20)|save');
223161
}).toThrow('The modifier "debounce()" does not support multiple arguments.')
224162
});
225-
226-
it('modifier cannot have named arguments', () => {
227-
expect(() => {
228-
parseDirectives('debounce(foo=bar)|save');
229-
}).toThrow('The modifier "debounce()" does not support named arguments.')
230-
});
231163
});
232164
});

src/LiveComponent/assets/test/controller/action.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,14 @@ describe('LiveController Action Tests', () => {
8181
data-live-action-param="sendNamedArgs"
8282
data-live-a-param="1"
8383
data-live-b-param="2"
84-
data-live-c-param="3"
84+
data-live-c-param="banana"
8585
>Send named args</button>
8686
</div>
8787
`);
8888

8989
// ONLY a post is sent, not a re-render GET
9090
test.expectsAjaxCall()
91-
.expectActionCalled('sendNamedArgs', {a: '1', b: '2', c: '3'})
91+
.expectActionCalled('sendNamedArgs', {a: 1, b: 2, c: 'banana'})
9292
.serverWillChangeProps((data: any) => {
9393
// server marks component as "saved"
9494
data.isSaved = true;
@@ -185,7 +185,7 @@ describe('LiveController Action Tests', () => {
185185
test.expectsAjaxCall()
186186
// 3 actions called
187187
.expectActionCalled('save')
188-
.expectActionCalled('sync', { syncAll: '1' })
188+
.expectActionCalled('sync', { syncAll: 1 })
189189
.expectActionCalled('save')
190190
.serverWillChangeProps((data: any) => {
191191
data.isSaved = true;

src/LiveComponent/assets/test/controller/emit.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@ describe('LiveController Emit Tests', () => {
2626
Render Count: ${data.renderCount}
2727
<button
2828
data-action="live#emit"
29-
data-event="fooEvent"
29+
data-live-event-param="fooEvent"
3030
>Emit Simple</button>
3131
3232
<button
3333
data-action="live#emit"
34-
data-event="name(simple-component)|fooEvent"
34+
data-live-event-param="name(simple-component)|fooEvent"
3535
>Emit Named Matching</button>
3636
3737
<button
3838
data-action="live#emit"
39-
data-event="name(other-component)|fooEvent"
39+
data-live-event-param="name(other-component)|fooEvent"
4040
>Emit Named Not Matching</button>
4141
</div>
4242
`);

src/LiveComponent/doc/index.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2462,7 +2462,7 @@ There are three ways to emit an event:
24622462

24632463
<button
24642464
data-action="live#emit"
2465-
data-event="productAdded"
2465+
data-live-event-param="productAdded"
24662466
>
24672467

24682468
2. From your PHP component via ``ComponentToolsTrait``::
@@ -2559,7 +2559,7 @@ If you want to emit an event to only the parent components, use the
25592559

25602560
<button
25612561
data-action="live#emitUp"
2562-
data-event="productAdded"
2562+
data-live-event-param="productAdded"
25632563
>
25642564

25652565
Or, in PHP::
@@ -2576,7 +2576,7 @@ use the ``name()`` modifier:
25762576

25772577
<button
25782578
data-action="live#emit"
2579-
data-event="name(ProductList)|productAdded"
2579+
data-live-event-param="name(ProductList)|productAdded"
25802580
>
25812581

25822582
Or, in PHP::
@@ -2592,7 +2592,7 @@ To emit an event to only yourself, use the ``emitSelf()`` method:
25922592

25932593
<button
25942594
data-action="live#emitSelf"
2595-
data-event="productAdded"
2595+
data-live-event-param="productAdded"
25962596
>
25972597

25982598
Or, in PHP::

0 commit comments

Comments
 (0)