Skip to content

Commit

Permalink
Improve listener controller
Browse files Browse the repository at this point in the history
  • Loading branch information
tabuna committed Nov 3, 2024
1 parent 71dec0d commit 6c941ca
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 24 deletions.
2 changes: 1 addition & 1 deletion public/js/orchid.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/mix-manifest.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 16 additions & 5 deletions resources/js/controllers/application_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,28 @@ export default class ApplicationController extends Controller {
}

/**
* Loads a Turbo Stream from the given URL with the specified data,
* and optionally invokes a callback after the main handler.
*
* @param url
* @param data
* @param {string} url - The endpoint to send the request to.
* @param {Object} data - The data payload for the request.
* @param {Function} [callback] - Optional callback to execute after the main handler.
*
* @returns {Promise} - A promise that resolves when the stream message is processed.
*/
loadStream(url, data) {
return window.axios.post(url, data, {
loadStream(url, data, callback = null) {
return window.axios.post(url, data, {
headers: {
Accept: "text/vnd.turbo-stream.html",
},
})
.then(response => response.data)
.then(html => Turbo.renderStreamMessage(html))
.then(html => {
Turbo.renderStreamMessage(html);
if (typeof callback === 'function') {
callback(html);
}
});
}

}
47 changes: 37 additions & 10 deletions resources/js/controllers/listener_controller.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
import ApplicationController from "./application_controller";

export default class extends ApplicationController {
static classes = [ "loading" ]
static values = {
url: {
type: String,
},
watched: {
type: Array,
default: [],
},
}

/**
*
*/
connect() {
this.targets.forEach(name => {
this.fieldsValue.forEach(name => {
document.querySelectorAll(`[name="${name}"]`)
.forEach((field) =>
field.addEventListener('change', () => this.asyncLoadData())
field.addEventListener('change', () => this.debouncedHandleFieldChange())
);
});
}

/**
*
* Handles the change event on the target fields by asynchronously loading data.
*/
asyncLoadData() {
const data = new FormData(this.element.closest('form'));
handleFieldChange() {
const formElement = this.element.closest('form');
formElement.classList.add(...this.loadingClasses);

const data = new FormData(formElement);

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

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


this.loadStream(this.data.get('async-route'), data);
this.loadStream(this.urlValue, data, () => {
formElement.classList.remove(...this.loadingClasses);
});
}

/**
* Debounced version of handleFieldChange to prevent multiple rapid requests.
*/
debouncedHandleFieldChange = this.debounce(() => this.handleFieldChange(), 200);


/**
* Utility function to debounce another function.
*
* @returns {any}
* @param {Function} func - The function to debounce.
* @param {number} wait - The debounce delay in milliseconds.
* @returns {Function} - A debounced function.
*/
get targets() {
return JSON.parse(this.data.get('targets'));
debounce(func, wait) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
}
10 changes: 3 additions & 7 deletions resources/views/layouts/listener.blade.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
<x-orchid-stream :target="$templateSlug" :rule="\request()->routeIs('platform.async.listener')">
<div data-controller="listener"
data-listener-targets="{{$targets}}"
data-listener-watched-value="{{$targets}}"
data-listener-url-value="{{$asyncRoute}}"
data-listener-loading-class="pe-none cursor-wait"
id="{{$templateSlug}}"
data-listener-async-route="{{$asyncRoute}}"

{{--
data-listener-slug="{{$templateSlug}}"
data-listener-async-enable="{{$asyncEnable}}"
--}}
>
@foreach($manyForms as $layouts)
@foreach($layouts as $layout)
Expand Down

0 comments on commit 6c941ca

Please sign in to comment.