import { Controller } from '@hotwired/stimulus'; import throttle from 'lodash/throttle'; /** * FormSubmitController * - 폼 제출을 처리하는 컨트롤러 * - submit 이벤트를 throttle로 제한하여 과도한 요청 방지 * - intervalValue를 통해 제출 간격을 조정할 수 있음 * - handleSubmit 메서드를 통해 폼을 제출하고, handleThrottledSubmit 메서드를 통해 throttled 제출을 처리 * * - intervalValue는 기본값으로 1000ms(1초)를 사용 * * - enabledValue를 통해 폼 제출을 활성화/비활성화할 수 있음 * * - handleSubmit 메서드는 폼의 params를 hidden input으로 변환하여 제출함 */ export default class extends Controller { static values = { interval: { type: Number, default: 1000 }, enabled: { type: Boolean, default: true }, }; connect() { // throttle로 감싸서 저장 주기 제한 this.throttledSave = throttle(this.handleSubmit.bind(this), this.intervalValue); } handleSubmit(event) { if (!this.enabledValue) { console.warn('Form submission is disabled.'); return; } const params = event?.params || {}; // 기존에 붙었던 hidden input 제거 (중복 방지) Object.keys(params).forEach((key) => { const snakeKey = this._toSnakeCase(key); const existing = this.element.querySelector(`input[name="${snakeKey}"]`); if (existing) existing.remove(); }); // 새로운 hidden input 추가 Object.entries(params).forEach(([key, value]) => { const snakeKey = this._toSnakeCase(key); const input = document.createElement('input'); input.type = 'hidden'; input.name = snakeKey; input.value = value; this.element.appendChild(input); }); this.element.requestSubmit(); } handleThrottledSubmit() { if (!this.enabledValue) { console.warn('Form submission is disabled.'); return; } this.throttledSave(); } _toSnakeCase(str) { return str .replace(/([a-z0-9])([A-Z])/g, '1ドル_2ドル') // camelCase → snake_case .replace(/[\s\-]+/g, '_') // 공백/하이픈 → 언더바 .replace(/([A-Z]+)([A-Z][a-z])/g, '1ドル_2ドル') // PascalCase 대응 .toLowerCase(); } }