2020-07-04 23:53:02 +08:00
|
|
|
import {onEnterPress, onSelect} from "../services/dom";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ajax Form
|
|
|
|
* Will handle button clicks or input enter press events and submit
|
|
|
|
* the data over ajax. Will always expect a partial HTML view to be returned.
|
|
|
|
* Fires an 'ajax-form-success' event when submitted successfully.
|
2020-07-25 07:20:58 +08:00
|
|
|
*
|
|
|
|
* Will handle a real form if that's what the component is added to
|
|
|
|
* otherwise will act as a fake form element.
|
|
|
|
*
|
2020-07-04 23:53:02 +08:00
|
|
|
* @extends {Component}
|
|
|
|
*/
|
|
|
|
class AjaxForm {
|
|
|
|
setup() {
|
|
|
|
this.container = this.$el;
|
2020-07-25 07:20:58 +08:00
|
|
|
this.responseContainer = this.container;
|
2020-07-04 23:53:02 +08:00
|
|
|
this.url = this.$opts.url;
|
|
|
|
this.method = this.$opts.method || 'post';
|
|
|
|
this.successMessage = this.$opts.successMessage;
|
|
|
|
this.submitButtons = this.$manyRefs.submit || [];
|
|
|
|
|
2020-07-25 07:20:58 +08:00
|
|
|
if (this.$opts.responseContainer) {
|
|
|
|
this.responseContainer = this.container.closest(this.$opts.responseContainer);
|
|
|
|
}
|
|
|
|
|
2020-07-04 23:53:02 +08:00
|
|
|
this.setupListeners();
|
|
|
|
}
|
|
|
|
|
|
|
|
setupListeners() {
|
2020-07-25 07:20:58 +08:00
|
|
|
|
|
|
|
if (this.container.tagName === 'FORM') {
|
|
|
|
this.container.addEventListener('submit', this.submitRealForm.bind(this));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-04 23:53:02 +08:00
|
|
|
onEnterPress(this.container, event => {
|
2020-07-25 07:20:58 +08:00
|
|
|
this.submitFakeForm();
|
2020-07-04 23:53:02 +08:00
|
|
|
event.preventDefault();
|
|
|
|
});
|
|
|
|
|
2020-07-25 07:20:58 +08:00
|
|
|
this.submitButtons.forEach(button => onSelect(button, this.submitFakeForm.bind(this)));
|
2020-07-04 23:53:02 +08:00
|
|
|
}
|
|
|
|
|
2020-07-25 07:20:58 +08:00
|
|
|
submitFakeForm() {
|
2020-07-04 23:53:02 +08:00
|
|
|
const fd = new FormData();
|
|
|
|
const inputs = this.container.querySelectorAll(`[name]`);
|
|
|
|
for (const input of inputs) {
|
|
|
|
fd.append(input.getAttribute('name'), input.value);
|
|
|
|
}
|
2020-07-25 07:20:58 +08:00
|
|
|
this.submit(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
submitRealForm(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
const fd = new FormData(this.container);
|
|
|
|
this.submit(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
async submit(formData) {
|
|
|
|
this.responseContainer.style.opacity = '0.7';
|
|
|
|
this.responseContainer.style.pointerEvents = 'none';
|
2020-07-04 23:53:02 +08:00
|
|
|
|
|
|
|
try {
|
2020-07-25 07:20:58 +08:00
|
|
|
const resp = await window.$http[this.method.toLowerCase()](this.url, formData);
|
|
|
|
this.$emit('success', {formData});
|
|
|
|
this.responseContainer.innerHTML = resp.data;
|
2020-07-04 23:53:02 +08:00
|
|
|
if (this.successMessage) {
|
|
|
|
window.$events.emit('success', this.successMessage);
|
|
|
|
}
|
|
|
|
} catch (err) {
|
2020-07-25 07:20:58 +08:00
|
|
|
this.responseContainer.innerHTML = err.data;
|
2020-07-04 23:53:02 +08:00
|
|
|
}
|
|
|
|
|
2020-07-25 07:20:58 +08:00
|
|
|
window.components.init(this.responseContainer);
|
|
|
|
this.responseContainer.style.opacity = null;
|
|
|
|
this.responseContainer.style.pointerEvents = null;
|
2020-07-04 23:53:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
export default AjaxForm;
|