Skip to content

Commit ae17486

Browse files
authored
[PBNTR-798] Make Date Picker Work within Turbo Frames (#4142)
**What does this PR do?** A clear and concise description with your runway ticket url. [PBNTR-798](https://runway.powerhrg.com/backlog_items/PBNTR-798) is a follow up to the investigation in [PBNTR-573](https://runway.powerhrg.com/backlog_items/PBNTR-573). It adds a `custom_event_type` prop which can be used as a hook for a dev to get any desired event (e.g. click, keyboard, or Turbo) to re-trigger a DOMContentLoaded event. Nitro devs can use this to update the value of a Rails DatePicker without reloading the entire page. **Screenshots:** Screenshots to visualize your addition/change <img width="1611" alt="doc ex and console after solve console errors" src="https://github.com/user-attachments/assets/52b4f696-d94d-47da-8c63-01a8d8dd43a5" /> **How to test?** Steps to confirm the desired behavior: 1. Go to Rails DatePicker page - [Within Turbo Frames doc example](https://pr4142.playbook.beta.px.powerapp.cloud/kits/date_picker#within-turbo-frames). 2. Click on the DatePicker, it should work as usual. The button click should submit a console log. This doc example is not fully wired up like it would be in a real world application, this is just a demonstration. 3. Other datepickers on the page should also work as expected. #### Checklist: - [x] **LABELS** Add a label: `enhancement`, `bug`, `improvement`, `new kit`, `deprecated`, or `breaking`. See [Changelog & Labels](https://github.com/powerhome/playbook/wiki/Changelog-&-Labels) for details. - [x] **DEPLOY** I have added the `milano` label to show I'm ready for a review. ~~- [ ] **TESTS** I have added test coverage to my code.~~
1 parent 471dc72 commit ae17486

File tree

5 files changed

+41
-10
lines changed

5 files changed

+41
-10
lines changed

Diff for: playbook/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb

+22-10
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,30 @@
6464
</div>
6565

6666
<%= javascript_tag do %>
67-
window.addEventListener("DOMContentLoaded", () => {
68-
datePickerHelper(<%= object.date_picker_config %>, "<%= object.scroll_container %>")
67+
(function() {
68+
const loadDatePicker = () => {
69+
datePickerHelper(<%= object.date_picker_config %>, "<%= object.scroll_container %>")
6970

70-
if (<%= object.selection_type == "quickpick" %>) {
71-
document.getElementById("<%= object.picker_id %>").addEventListener("change", ({ target }) => {
72-
const startDate = document.getElementById("<%= object.start_date_id %>")
73-
const endDate = document.getElementById("<%= object.end_date_id %>")
74-
const splittedValue = target.value.split(" to ")
75-
startDate.value = splittedValue[0]
76-
endDate.value = splittedValue[1] ? splittedValue[1] : splittedValue[0]
71+
if (<%= object.selection_type == "quickpick" %>) {
72+
document.getElementById("<%= object.picker_id %>").addEventListener("change", ({ target }) => {
73+
const startDate = document.getElementById("<%= object.start_date_id %>")
74+
const endDate = document.getElementById("<%= object.end_date_id %>")
75+
const splittedValue = target.value.split(" to ")
76+
startDate.value = splittedValue[0]
77+
endDate.value = splittedValue[1] ? splittedValue[1] : splittedValue[0]
78+
})
79+
}
80+
}
81+
82+
window.addEventListener("DOMContentLoaded", () => {
83+
loadDatePicker()
84+
})
85+
86+
if (<%= !object.custom_event_type.empty? %>) {
87+
window.addEventListener("<%= object.custom_event_type %>", () => {
88+
loadDatePicker()
7789
})
7890
}
79-
})
91+
})()
8092
<% end %>
8193
<% end %>

Diff for: playbook/app/pb_kits/playbook/pb_date_picker/date_picker.rb

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class DatePicker < Playbook::KitBase
7373
default: false
7474
prop :year_range, type: Playbook::Props::Array,
7575
default: [1900, 2100]
76+
prop :custom_event_type, type: Playbook::Props::String,
77+
default: ""
7678

7779
def classname
7880
default_margin_bottom = margin_bottom.present? ? "" : " mb_sm"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<%= pb_rails("date_picker", props: { picker_id: "date-picker-turbo-frames", custom_event_type: "datePickerLoader" }) %>
2+
<%= pb_rails("button", props: { id: "date-picker-loader", text: "Click Event Simulation" }) %>
3+
4+
<script>
5+
document.getElementById("date-picker-loader").addEventListener("click", () => {
6+
window.document.dispatchEvent(
7+
new CustomEvent("datePickerLoader", {
8+
bubbles: true,
9+
})
10+
)
11+
console.log("Event 'datePickerLoader' dispatched - in a real implementation, this event would trigger the date picker's reinitialization through the custom_event_type prop connection")
12+
})
13+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The `custom_event_type` prop allows you to specify a custom event that will trigger the date picker's initialization, in addition to the default initialization on `DOMContentLoaded`. This is particularly useful in dynamic contexts like Turbo Frame updates where you need to reinitialize the date picker after new content loads. For Turbo integration, use `custom_event_type: "turbo:before-render"` to ensure the date picker properly reinitializes after Turbo navigation events.
2+
3+
In this example, we demonstrate the setup pattern by connecting a button to dispatch a "datePickerLoader" event - while the date picker's event listener is properly configured through the `custom_event_type` prop, this demo only logs the event dispatch to the console to illustrate the connection structure.

Diff for: playbook/app/pb_kits/playbook/pb_date_picker/docs/example.yml

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ examples:
2828
- date_picker_time: Time Selection
2929
- date_picker_positions: Custom Positions
3030
- date_picker_positions_element: Custom Position (based on element)
31+
- date_picker_turbo_frames: Within Turbo Frames
3132

3233
react:
3334
- date_picker_default: Default

0 commit comments

Comments
 (0)