Skip to content

Commit f36152d

Browse files
committed
Improve listener controller
1 parent ec4c046 commit f36152d

File tree

5 files changed

+58
-24
lines changed

5 files changed

+58
-24
lines changed

public/js/orchid.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/mix-manifest.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

resources/js/controllers/application_controller.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,28 @@ export default class ApplicationController extends Controller {
6767
}
6868

6969
/**
70+
* Loads a Turbo Stream from the given URL with the specified data,
71+
* and optionally invokes a callback after the main handler.
7072
*
71-
* @param url
72-
* @param data
73+
* @param {string} url - The endpoint to send the request to.
74+
* @param {Object} data - The data payload for the request.
75+
* @param {Function} [callback] - Optional callback to execute after the main handler.
76+
*
77+
* @returns {Promise} - A promise that resolves when the stream message is processed.
7378
*/
74-
loadStream(url, data) {
75-
return window.axios.post(url, data, {
79+
loadStream(url, data, callback = null) {
80+
return window.axios.post(url, data, {
7681
headers: {
7782
Accept: "text/vnd.turbo-stream.html",
7883
},
7984
})
8085
.then(response => response.data)
81-
.then(html => Turbo.renderStreamMessage(html))
86+
.then(html => {
87+
Turbo.renderStreamMessage(html);
88+
if (typeof callback === 'function') {
89+
callback(html);
90+
}
91+
});
8292
}
93+
8394
}
Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,37 @@
11
import ApplicationController from "./application_controller";
22

33
export default class extends ApplicationController {
4+
static classes = [ "loading" ]
5+
static values = {
6+
url: {
7+
type: String,
8+
},
9+
watched: {
10+
type: Array,
11+
default: [],
12+
},
13+
}
14+
415
/**
516
*
617
*/
718
connect() {
8-
this.targets.forEach(name => {
19+
this.fieldsValue.forEach(name => {
920
document.querySelectorAll(`[name="${name}"]`)
1021
.forEach((field) =>
11-
field.addEventListener('change', () => this.asyncLoadData())
22+
field.addEventListener('change', () => this.debouncedHandleFieldChange())
1223
);
1324
});
1425
}
1526

1627
/**
17-
*
28+
* Handles the change event on the target fields by asynchronously loading data.
1829
*/
19-
asyncLoadData() {
20-
const data = new FormData(this.element.closest('form'));
30+
handleFieldChange() {
31+
const formElement = this.element.closest('form');
32+
formElement.classList.add(...this.loadingClasses);
2133

34+
const data = new FormData(formElement);
2235

2336
let state = document.getElementById('screen-state').value;
2437

@@ -27,15 +40,29 @@ export default class extends ApplicationController {
2740
data.append('_state', state)
2841
}
2942

30-
31-
this.loadStream(this.data.get('async-route'), data);
43+
this.loadStream(this.urlValue, data, () => {
44+
formElement.classList.remove(...this.loadingClasses);
45+
});
3246
}
3347

3448
/**
49+
* Debounced version of handleFieldChange to prevent multiple rapid requests.
50+
*/
51+
debouncedHandleFieldChange = this.debounce(() => this.handleFieldChange(), 200);
52+
53+
54+
/**
55+
* Utility function to debounce another function.
3556
*
36-
* @returns {any}
57+
* @param {Function} func - The function to debounce.
58+
* @param {number} wait - The debounce delay in milliseconds.
59+
* @returns {Function} - A debounced function.
3760
*/
38-
get targets() {
39-
return JSON.parse(this.data.get('targets'));
61+
debounce(func, wait) {
62+
let timeout;
63+
return (...args) => {
64+
clearTimeout(timeout);
65+
timeout = setTimeout(() => func.apply(this, args), wait);
66+
};
4067
}
4168
}

resources/views/layouts/listener.blade.php

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
<x-orchid-stream :target="$templateSlug" :rule="\request()->routeIs('platform.async.listener')">
22
<div data-controller="listener"
3-
data-listener-targets="{{$targets}}"
3+
data-listener-watched-value="{{$targets}}"
4+
data-listener-url-value="{{$asyncRoute}}"
5+
data-listener-loading-class="pe-none cursor-wait"
46
id="{{$templateSlug}}"
5-
data-listener-async-route="{{$asyncRoute}}"
6-
7-
{{--
8-
data-listener-slug="{{$templateSlug}}"
9-
data-listener-async-enable="{{$asyncEnable}}"
10-
--}}
117
>
128
@foreach($manyForms as $layouts)
139
@foreach($layouts as $layout)

0 commit comments

Comments
 (0)