I am using FullCalendar for a project and want to catch the clicks to the actual calendar and make appointments that way via popup modal. But the atom is not ready when I click on the widget and I get cannot read props.
I'm running into some issues because i have an app-state atom that is defined at the top of my core.cljs file, and it is not initialized when someone clicks the calendar widget.
I keep getting cannot read properties of undefined (reading 'app-state')
I'm wondering if there's a way to delay things so that it will work? I tried delaying to "onload" but that doesn't work neither
I think ^:export is part of the solution but I'm not sure what else
We need more details to provide any kind of help.
What's FullCalendar? What's the source code? What's app-state? And so on.
Let's see...
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.15/index.global.min.js'></script> is the fullcalendar drop-in
Grok gave
<script>
var globalCalendar;
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
if (calendarEl) {
globalCalendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'timeGridWeek',
dateClick: function(info) {
console.log('Date clicked:', info.dateStr, 'Date object:', info.date);
if (window.tomyappt005 && window.tomyappt005.handleDateClick) {
window.tomyappt005.handleDateClick(info.dateStr);
} else {
console.error('tomyappt005.handleDateClick not found');
}
},
slotMinTime: "08:00:00",
slotMaxTime: "18:00:00",
allDaySlot: false
});
globalCalendar.render();
} else {
console.error('Calendar element not found');
}
});
</script>
as a way to pass the date to handleDateClick in the clojurescript appThen I have a clojurescript part that goes something like
(set! (.-tomyappt005 js/window) #js {})
(set! (.-handleDateClick (.-tomyappt005 js/window))
(fn [date-str]
(js/console.log "ClojureScript received click for date:" date-str)
(swap! appstate assoc
:show-modal true
:modal-date date-str)))in theory that should capture the date-str and swap the appstate atom which looks like
(defonce appstate
(r/atom {:polled-data {}
:current-user {:id 1
:role "admin"}
:forms {:appointment {}
:user {}
:client {}
:insurance {}
:service {}}
:last-refresh nil
:show-modal false ;; Add for modal visibility
:modal-date nil ;; Store clicked date
:search {:type :interpreter
:selected-id nil
:start-date nil
:end-date nil
:results []
:selected-appointments #{}}}))... when I click on the page I do get the handleDateClick to print out that it got the date, but then the swap fails
Wow, OK.
So, to get it out of the way - IMO if you're a beginner, you really, really should not be using an LLM to generate some awful garbage for you.
All that stuff with DOMContentLoaded, js/window, ^:export is literally the worst way to do it, and cannot work in principle if the element with id="calendar" is created by Reagent.
the calendar is hard-coded into the page basically, it's the appstate that's a reagent atom
What I would do instead:
1. Install fullcalendar as a proper NPM dependency as opposed to using it via a CDN
2. Import Calendar
3. Create a Reagent component that wraps Calendar and passes it a DOM node via a ref and any handlers as plain function objects
That's is, easy-peasy.
The only possible hiccup is the first item, but the chance of something going wrong is about 1%.
oh, don't use it via CDN? that makes sense. there's probably some good documentation about npm deps via cljs?
If you use shadow-cljs, the docs are perfect, yes. No clue about vanilla of figwheel-main - I haven't used those in many years.
yeah it's shadow-cljs here
is there a logical reason something like this won't work though?
(def handleDateClickVal (atom nil))
(set! (.-tomyappt005 js/window) #js {})
(set! (.-handleDateClick (.-tomyappt005 js/window))
(fn [date-str]
(js/console.log "ClojureScript received click for date:" date-str)
(swap! handleDateClickVal assoc
:show-modal true
:modal-date date-str)))
that is, make a new atom, and then swap! the atom with the handleDateClick that gets invoked from the widget?I'm a little confused by what you mean by "Import Calendar" you mean in the requires/imports?
> is there a logical reason something like this won't work though?
It can fail in an optimized build if any of the fields that you set are minified in CLJS code but aren't minified in the JS code extrinsic to the CLJS code. But maybe fields that get set! on js/something directly or transitively aren't minified - I don't know.
> you mean in the requires/imports?
Yes, just like the README of FullCalendar suggests in its repo. Of course, it talks about JS imports but you can translate those to CLJS with the help of shadow-cljs docs.
Okay cool. I will ask in shadow-cljs about the npm dependency. Ty
Nice! I was able to import the Calendar so now I can use native methods on it? What did you mean by reagent component that wraps the cal?
err spoke too soon, don't have it working quite yet ...
okay i needed some extra plugins. it's rendering now ^_^
hey I got it working! 😄