Skip to content

Instantly share code, notes, and snippets.

@awd
Created January 16, 2024 16:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save awd/16df51e8e2e8dab42b1af4004ae6ba56 to your computer and use it in GitHub Desktop.
Save awd/16df51e8e2e8dab42b1af4004ae6ba56 to your computer and use it in GitHub Desktop.
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
static targets = ['launcher']
initialize () {
this.launchModal = this.launchModal.bind(this)
}
connect () {
// need to manually reference instead of using a stimulus target (the target disconnects when the iframe opens)
this.modalTarget = document.getElementById('your-modal-id')
this.launcherTarget.addEventListener('click', this.launchModal)
// stimulus targets and listeners are disconnected when modal opens (iframe) - setup manually here instead
this.formTarget = this.modalTarget.querySelector('form')
this.submitButton = this.modalTarget.querySelector('ui-title-bar button[variant="primary"]')
this.cancelButton = this.modalTarget.querySelector('ui-title-bar button:not([variant="primary"])')
this.formTarget.addEventListener('submit', this.submitForm.bind(this))
this.submitButton.addEventListener('click', this.submitButtonClicked.bind(this))
this.cancelButton.addEventListener('click', this.cancelButtonClicked.bind(this))
this.modalTarget.addEventListener('hide', (_event) => {
this.formTarget.reset()
})
}
disconnect () {
this.launcherTarget.removeEventListener('click', this.launchModal)
}
launchModal (_event) {
this.modalTarget.show()
}
submitButtonClicked (event) {
event.preventDefault()
this.formTarget.requestSubmit()
}
cancelButtonClicked (event) {
event.preventDefault()
this.modalTarget.hide()
}
async submitForm (event) {
event.preventDefault()
const sessionToken = await shopify.idToken()
const formData = new FormData(this.formTarget)
// convert to params Rails will know how to accept
const encodedData = new URLSearchParams(formData).toString()
fetch(event.target.action, {
method: formData.get('_method') ? formData.get('_method').toUpperCase() : 'POST',
headers: {
Authorization: `Bearer ${sessionToken}`,
Accept: 'text/vnd.turbo-stream.html',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: encodedData
}).catch(error => {
console.error(error)
})
// set new defaults after form submission, so reset() via hide() doesn't override to old values
this.formTarget.querySelectorAll('input').forEach(input => {
if (input.type === 'checkbox') {
input.defaultChecked = input.checked
} else {
input.defaultValue = input.value
}
})
this.modalTarget.hide()
}
}
<div data-controller="your-controller">
<ui-modal id="your-modal-id" data-your-controller-target="modal" variant="base">
<form action="-add your rails route here- / -use rails form helper instead-">
... add your fields here
</form>
<ui-title-bar title="Set your custom modal title here">
<button variant="primary">Done</button>
<button>Cancel</button>
</ui-title-bar>
</ui-modal>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment