import Sortable from 'sortablejs'; export class RepeatLine extends HTMLDivElement{ connectedCallback(){ this.$props = this.getProps(this, { maxRows: 5 }); this.$refs = this.getRefs(this); this.rowHTML = this.$refs.rows.children[0].outerHTML; this.init(); } // Hook up events for the row. setUpRow(row) { const rowRefs = this.getRefs(row); rowRefs.removeButton.onclick = (e) => { e.preventDefault(); this.removeRow(row); }; } // Enable or disable addButton as necessary. updateAddButton() { if (this.$refs.rows.children.length >= this.$props.maxRows) { this.$refs.addButton.setAttribute('disabled', ''); return; } this.$refs.addButton.removeAttribute('disabled'); } // Update array key values to the row number updateFieldNames() { [...this.$refs.rows.children] .forEach((el, index) => { el.querySelectorAll('[name]') .forEach(el => { const newName = el.getAttribute('name').replace(/\[\d\]/gm, `[${index}]`); el.setAttribute('name', newName); }); }); } addRow() { if ( !this.rowHTML || this.$refs.rows.children.length >= this.$props.maxRows ) return; let newRow = this.createFromHTML(this.rowHTML); newRow.removeAttribute('id'); this.setUpRow(newRow); this.$refs.rows.appendChild(newRow); newRow.querySelector('input,textarea,select').focus(); newRow.querySelectorAll('input,textarea,select').forEach(el=>{ el.setAttribute('value',''); el.value = ""; }) this.updateFieldNames(); this.updateAddButton(); } removeRow(row) { if (this.$refs.rows.children.length <= 1) return; row.remove(); this.$refs.rows.focus(); this.updateFieldNames(); this.updateFieldNames(); } init() { this.setUpRow(this.$refs.rows.children[0]); this.$refs.addButton.onclick = (e) => { e.preventDefault(); this.addRow(); } this.updateFieldNames(); let repeater__rows = this.querySelector('.form-repeater__rows'); new Sortable(repeater__rows,{ }); } // Return an object that contains references to DOM objects. getRefs(el) { let result = {}; [...el.querySelectorAll('[data-ref]')] .forEach(ref => { result[ref.dataset.ref] = ref; }); return result; } setDefaults(obj, defaults) { let results = obj; for (const prop in defaults) { if (!obj.hasOwnProperty(prop)) { results[prop] = defaults[prop]; } } return results; } getProps(el, defaults={}) { return this.setDefaults( JSON.parse(el.dataset.props ?? '{}'), defaults ); } createFromHTML(html='') { let element = document.createElement(null); element.innerHTML = html; return element.firstElementChild; } }