]> BookStack Code Mirror - bookstack/blob - resources/js/components/ajax-form.js
Started refactor and alignment of component system
[bookstack] / resources / js / components / ajax-form.js
1 import {onEnterPress, onSelect} from "../services/dom";
2 import {Component} from "./component";
3
4 /**
5  * Ajax Form
6  * Will handle button clicks or input enter press events and submit
7  * the data over ajax. Will always expect a partial HTML view to be returned.
8  * Fires an 'ajax-form-success' event when submitted successfully.
9  *
10  * Will handle a real form if that's what the component is added to
11  * otherwise will act as a fake form element.
12  */
13 export class AjaxForm extends Component {
14     setup() {
15         this.container = this.$el;
16         this.responseContainer = this.container;
17         this.url = this.$opts.url;
18         this.method = this.$opts.method || 'post';
19         this.successMessage = this.$opts.successMessage;
20         this.submitButtons = this.$manyRefs.submit || [];
21
22         if (this.$opts.responseContainer) {
23             this.responseContainer = this.container.closest(this.$opts.responseContainer);
24         }
25
26         this.setupListeners();
27     }
28
29     setupListeners() {
30
31         if (this.container.tagName === 'FORM') {
32             this.container.addEventListener('submit', this.submitRealForm.bind(this));
33             return;
34         }
35
36         onEnterPress(this.container, event => {
37             this.submitFakeForm();
38             event.preventDefault();
39         });
40
41         this.submitButtons.forEach(button => onSelect(button, this.submitFakeForm.bind(this)));
42     }
43
44     submitFakeForm() {
45         const fd = new FormData();
46         const inputs = this.container.querySelectorAll(`[name]`);
47         for (const input of inputs) {
48             fd.append(input.getAttribute('name'), input.value);
49         }
50         this.submit(fd);
51     }
52
53     submitRealForm(event) {
54         event.preventDefault();
55         const fd = new FormData(this.container);
56         this.submit(fd);
57     }
58
59     async submit(formData) {
60         this.responseContainer.style.opacity = '0.7';
61         this.responseContainer.style.pointerEvents = 'none';
62
63         try {
64             const resp = await window.$http[this.method.toLowerCase()](this.url, formData);
65             this.$emit('success', {formData});
66             this.responseContainer.innerHTML = resp.data;
67             if (this.successMessage) {
68                 window.$events.emit('success', this.successMessage);
69             }
70         } catch (err) {
71             this.responseContainer.innerHTML = err.data;
72         }
73
74         window.$components.init(this.responseContainer);
75         this.responseContainer.style.opacity = null;
76         this.responseContainer.style.pointerEvents = null;
77     }
78
79 }