mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 03:51:09 -05:00
Refactor designer, manufacturer, and ride model forms to utilize Alpine.js for state management. Improved form submission handling, HTMX event integration, and enhanced user experience through better event dispatching and modal management.
This commit is contained in:
@@ -1,35 +1,66 @@
|
||||
{% load static %}
|
||||
|
||||
<form method="post"
|
||||
class="space-y-6"
|
||||
x-data="{ submitting: false }"
|
||||
@submit.prevent="
|
||||
if (!submitting) {
|
||||
submitting = true;
|
||||
const formData = new FormData($event.target);
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('designerForm', () => ({
|
||||
submitting: false,
|
||||
|
||||
init() {
|
||||
// Listen for HTMX events on this form
|
||||
this.$el.addEventListener('htmx:afterRequest', (event) => {
|
||||
if (event.detail.pathInfo.requestPath === '/rides/designers/create/') {
|
||||
this.handleResponse(event);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
async submitForm(event) {
|
||||
if (this.submitting) return;
|
||||
|
||||
this.submitting = true;
|
||||
const formData = new FormData(event.target);
|
||||
const csrfToken = this.$el.querySelector('[name=csrfmiddlewaretoken]').value;
|
||||
|
||||
// Use HTMX for form submission
|
||||
htmx.ajax('POST', '/rides/designers/create/', {
|
||||
values: Object.fromEntries(formData),
|
||||
headers: {
|
||||
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
|
||||
}
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
target: this.$el,
|
||||
swap: 'none'
|
||||
});
|
||||
},
|
||||
|
||||
handleResponse(event) {
|
||||
this.submitting = false;
|
||||
|
||||
// Handle HTMX response using event listeners
|
||||
document.addEventListener('htmx:afterRequest', function handleResponse(event) {
|
||||
if (event.detail.pathInfo.requestPath === '/rides/designers/create/') {
|
||||
document.removeEventListener('htmx:afterRequest', handleResponse);
|
||||
|
||||
if (event.detail.xhr.status >= 200 && event.detail.xhr.status < 300) {
|
||||
const data = JSON.parse(event.detail.xhr.response);
|
||||
if (typeof selectDesigner === 'function') {
|
||||
selectDesigner(data.id, data.name);
|
||||
}
|
||||
$dispatch('close-designer-modal');
|
||||
}
|
||||
submitting = false;
|
||||
}
|
||||
});
|
||||
}">
|
||||
if (event.detail.xhr.status >= 200 && event.detail.xhr.status < 300) {
|
||||
const data = JSON.parse(event.detail.xhr.response);
|
||||
|
||||
// Dispatch event with designer data for parent components
|
||||
this.$dispatch('designer-created', {
|
||||
id: data.id,
|
||||
name: data.name
|
||||
});
|
||||
|
||||
// Close modal if in modal context
|
||||
this.$dispatch('close-designer-modal');
|
||||
} else {
|
||||
// Handle error case
|
||||
this.$dispatch('designer-creation-error', {
|
||||
error: event.detail.xhr.responseText
|
||||
});
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
|
||||
<form method="post"
|
||||
class="space-y-6"
|
||||
x-data="designerForm()"
|
||||
@submit.prevent="submitForm($event)">
|
||||
{% csrf_token %}
|
||||
|
||||
<div id="designer-form-notification"></div>
|
||||
|
||||
@@ -1,35 +1,66 @@
|
||||
{% load static %}
|
||||
|
||||
<form method="post"
|
||||
class="space-y-6"
|
||||
x-data="{ submitting: false }"
|
||||
@submit.prevent="
|
||||
if (!submitting) {
|
||||
submitting = true;
|
||||
const formData = new FormData($event.target);
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('manufacturerForm', () => ({
|
||||
submitting: false,
|
||||
|
||||
init() {
|
||||
// Listen for HTMX events on this form
|
||||
this.$el.addEventListener('htmx:afterRequest', (event) => {
|
||||
if (event.detail.pathInfo.requestPath === '/rides/manufacturers/create/') {
|
||||
this.handleResponse(event);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
async submitForm(event) {
|
||||
if (this.submitting) return;
|
||||
|
||||
this.submitting = true;
|
||||
const formData = new FormData(event.target);
|
||||
const csrfToken = this.$el.querySelector('[name=csrfmiddlewaretoken]').value;
|
||||
|
||||
// Use HTMX for form submission
|
||||
htmx.ajax('POST', '/rides/manufacturers/create/', {
|
||||
values: Object.fromEntries(formData),
|
||||
headers: {
|
||||
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
|
||||
}
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
target: this.$el,
|
||||
swap: 'none'
|
||||
});
|
||||
},
|
||||
|
||||
handleResponse(event) {
|
||||
this.submitting = false;
|
||||
|
||||
// Handle HTMX response using event listeners
|
||||
document.addEventListener('htmx:afterRequest', function handleResponse(event) {
|
||||
if (event.detail.pathInfo.requestPath === '/rides/manufacturers/create/') {
|
||||
document.removeEventListener('htmx:afterRequest', handleResponse);
|
||||
|
||||
if (event.detail.xhr.status >= 200 && event.detail.xhr.status < 300) {
|
||||
const data = JSON.parse(event.detail.xhr.response);
|
||||
if (typeof selectManufacturer === 'function') {
|
||||
selectManufacturer(data.id, data.name);
|
||||
}
|
||||
$dispatch('close-manufacturer-modal');
|
||||
}
|
||||
submitting = false;
|
||||
}
|
||||
});
|
||||
}">
|
||||
if (event.detail.xhr.status >= 200 && event.detail.xhr.status < 300) {
|
||||
const data = JSON.parse(event.detail.xhr.response);
|
||||
|
||||
// Dispatch event with manufacturer data for parent components
|
||||
this.$dispatch('manufacturer-created', {
|
||||
id: data.id,
|
||||
name: data.name
|
||||
});
|
||||
|
||||
// Close modal if in modal context
|
||||
this.$dispatch('close-manufacturer-modal');
|
||||
} else {
|
||||
// Handle error case
|
||||
this.$dispatch('manufacturer-creation-error', {
|
||||
error: event.detail.xhr.responseText
|
||||
});
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
|
||||
<form method="post"
|
||||
class="space-y-6"
|
||||
x-data="manufacturerForm()"
|
||||
@submit.prevent="submitForm($event)">
|
||||
{% csrf_token %}
|
||||
|
||||
<div id="manufacturer-form-notification"></div>
|
||||
|
||||
@@ -1,53 +1,103 @@
|
||||
{% load static %}
|
||||
|
||||
<form method="post"
|
||||
class="space-y-6"
|
||||
x-data="{
|
||||
submitting: false,
|
||||
manufacturerSearchTerm: '',
|
||||
setManufacturerModal(value, term = '') {
|
||||
const parentForm = document.querySelector('[x-data]');
|
||||
if (parentForm) {
|
||||
const parentData = Alpine.$data(parentForm);
|
||||
if (parentData && parentData.setManufacturerModal) {
|
||||
parentData.setManufacturerModal(value, term);
|
||||
}
|
||||
}
|
||||
}
|
||||
}"
|
||||
@submit.prevent="
|
||||
if (!submitting) {
|
||||
submitting = true;
|
||||
const formData = new FormData($event.target);
|
||||
htmx.ajax('POST', '/rides/models/create/', {
|
||||
values: Object.fromEntries(formData),
|
||||
headers: {
|
||||
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('rideModelForm', () => ({
|
||||
submitting: false,
|
||||
manufacturerSearchTerm: '',
|
||||
|
||||
init() {
|
||||
// Listen for HTMX events on this form
|
||||
this.$el.addEventListener('htmx:afterRequest', (event) => {
|
||||
if (event.detail.pathInfo.requestPath === '/rides/models/create/') {
|
||||
this.handleResponse(event);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle HTMX response using event listeners
|
||||
document.addEventListener('htmx:afterRequest', function handleResponse(event) {
|
||||
if (event.detail.pathInfo.requestPath === '/rides/models/create/') {
|
||||
document.removeEventListener('htmx:afterRequest', handleResponse);
|
||||
|
||||
if (event.detail.xhr.status >= 200 && event.detail.xhr.status < 300) {
|
||||
const data = JSON.parse(event.detail.xhr.response);
|
||||
if (typeof selectRideModel === 'function') {
|
||||
selectRideModel(data.id, data.name);
|
||||
}
|
||||
const parentForm = document.querySelector('[x-data]');
|
||||
if (parentForm) {
|
||||
const parentData = Alpine.$data(parentForm);
|
||||
if (parentData && parentData.setRideModelModal) {
|
||||
parentData.setRideModelModal(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
submitting = false;
|
||||
}
|
||||
// Initialize form with any pre-filled values
|
||||
this.initializeForm();
|
||||
},
|
||||
|
||||
initializeForm() {
|
||||
const searchInput = this.$el.querySelector('#id_ride_model_search');
|
||||
const nameInput = this.$el.querySelector('#id_name');
|
||||
if (searchInput && searchInput.value && nameInput) {
|
||||
nameInput.value = searchInput.value;
|
||||
}
|
||||
},
|
||||
|
||||
setManufacturerModal(value, term = '') {
|
||||
// Dispatch event to parent component to handle manufacturer modal
|
||||
this.$dispatch('set-manufacturer-modal', {
|
||||
show: value,
|
||||
searchTerm: term
|
||||
});
|
||||
}">
|
||||
},
|
||||
|
||||
async submitForm(event) {
|
||||
if (this.submitting) return;
|
||||
|
||||
this.submitting = true;
|
||||
const formData = new FormData(event.target);
|
||||
const csrfToken = this.$el.querySelector('[name=csrfmiddlewaretoken]').value;
|
||||
|
||||
// Use HTMX for form submission
|
||||
htmx.ajax('POST', '/rides/models/create/', {
|
||||
values: Object.fromEntries(formData),
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
target: this.$el,
|
||||
swap: 'none'
|
||||
});
|
||||
},
|
||||
|
||||
handleResponse(event) {
|
||||
this.submitting = false;
|
||||
|
||||
if (event.detail.xhr.status >= 200 && event.detail.xhr.status < 300) {
|
||||
const data = JSON.parse(event.detail.xhr.response);
|
||||
|
||||
// Dispatch event with ride model data for parent components
|
||||
this.$dispatch('ride-model-created', {
|
||||
id: data.id,
|
||||
name: data.name
|
||||
});
|
||||
|
||||
// Close modal if in modal context
|
||||
this.$dispatch('close-ride-model-modal');
|
||||
} else {
|
||||
// Handle error case
|
||||
this.$dispatch('ride-model-creation-error', {
|
||||
error: event.detail.xhr.responseText
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
selectManufacturer(manufacturerId, manufacturerName) {
|
||||
// Update manufacturer fields using AlpineJS reactive approach
|
||||
const manufacturerInput = this.$el.querySelector('#id_manufacturer');
|
||||
const searchInput = this.$el.querySelector('#id_manufacturer_search');
|
||||
const resultsDiv = this.$el.querySelector('#manufacturer-search-results');
|
||||
|
||||
if (manufacturerInput) manufacturerInput.value = manufacturerId;
|
||||
if (searchInput) searchInput.value = manufacturerName;
|
||||
if (resultsDiv) resultsDiv.innerHTML = '';
|
||||
},
|
||||
|
||||
clearManufacturerResults() {
|
||||
const resultsDiv = this.$el.querySelector('#manufacturer-search-results');
|
||||
if (resultsDiv) resultsDiv.innerHTML = '';
|
||||
}
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
|
||||
<form method="post"
|
||||
class="space-y-6"
|
||||
x-data="rideModelForm()"
|
||||
@submit.prevent="submitForm($event)"
|
||||
@click.outside="clearManufacturerResults()">
|
||||
{% csrf_token %}
|
||||
|
||||
<div id="ride-model-notification"></div>
|
||||
|
||||
Reference in New Issue
Block a user