Skip to content

Instantly share code, notes, and snippets.

@minimul
Created June 21, 2021 15:38
Show Gist options
  • Save minimul/52b368eb78135729ff563fc136fbb8de to your computer and use it in GitHub Desktop.
Save minimul/52b368eb78135729ff563fc136fbb8de to your computer and use it in GitHub Desktop.
Kicking off JavaScript on a turbo stream
# Needed to close an open modal after streaming in a new select box
# 1. Newly generated select box. Mark "from-stream" true.
# app/views/shipments/create_entity.turbo_stream.erb
<%
dropdown_html = ""
form_with(model: form, url: result.action_url) do |f|
dropdown_html = render partial: "shipments/entity_dropdown",
locals: { f: f, type: type, collection: collection, from_stream: true }
end
%>
# 2. shipments/entity_dropdown.html.erb
<div id="<%= shipment_entity_dropdown_id(type) %>">
<%= f.select "#{type}_id".to_sym, collection,
{prompt: shipment_entity_prompt(type)},
{
data: {
"controller": "shipments--entity-dropdown",
"shipments--entity-dropdown-from-stream-value": defined?(from_stream) ? from_stream : false
}
}
%>
</div>
# 3. shipments/entity_dropdown_controller.js
# MutationObserver kicks off after the stream
# and fromStream value is now true
export default class extends Controller {
static values = { fromStream: Boolean }
connect () {
const limit = this.data.get('limit')
const placeholder = this.data.get('placeholder')
const searchText = this.data.get('no-results')
const closeOnSelect = this.single
const allowDeselect = !this.element.required
this.select = new SlimSelect({
select: this.element,
closeOnSelect,
allowDeselect,
limit,
placeholder,
searchText,
onChange: (info) => {
this.markAsSelected(info)
}
})
this.markAsSelected(this.element)
if (this.fromStreamValue) {
if (isVisible('#inner-modal-container')) {
Rails.fire(document, 'close-inner-modal')
} else {
Rails.fire(document, 'close-modal')
}
}
}
// ... more methods
}
# 4. When modal is opened create a custom event listener
# so modal can be closed.
export default class extends Modal {
static targets = ['container']
open (e) {
this.adjustWidth(e)
// Expose the ability to close the modal
this.element.dispatchEvent(new CustomEvent('close-modal', { bubbles: true }))
document.addEventListener('close-modal', () => { this.close(e) })
super.open(e)
}
close (e) {
document.removeEventListener('close-modal', this.close)
super.close(e)
}
disconnect () {
document.removeEventListener('close-modal', this.close)
super.disconnect()
}
// .. more methods
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment