naja-js / naja

Modern AJAX library for Nette Framework
https://naja.js.org
MIT License
109 stars 16 forks source link

Snippet caching problem when `afterUpdate` modifies snippet DOM #368

Closed zipper closed 7 months ago

zipper commented 1 year ago

I believe, that current snippet caching is not ideal, maybe even broken. When using some 3rd party JS libraries (eg. for select replacements, datepickers, dropdowns, tooltips, etc.), I struggle to get them working properly after ajax. More precisely, they work properly after ajax - using initialization on afterUpdate on snippet -, but they do not work properly when using browser back / forward buttons.

Right now, the "life cycle" of snippet is as follows:

Then on popstate:

This leads to problems. If the snippet during afterUpdate callback is modified, eg. by some JS library changing DOM and binding callbacks, these DOM changes (but not the binded events!) are also stored in cache. Then on restore, the JS library tries to initialize on already changed DOM. Which may cause errors - the library might not initialize correctly because some classes are changed, some DOM element properties might be lost, etc. That is out of our control and depends solely on 3rd party library itself.

I think that better way would be to store in cache exactly what you have received in payload. That makes more sense, because on popstate, you have complete options of original request (or you can retrieve them) and all the callbacks are executed as with real (original) ajax request. Therefore I expect those callbacks to be executed on the same code as from payload.

I think this should be the expected and correct behaviour - afterUpdate should always be executed on the same snippet content / DOM. We do not cache other DOM changes (validtion, etc.), so it does make sense to me, that we cache actual payload contents. Another reason for this behaviour could be, that you no longer need to consider if the cache is actually turned on or not - you don't need to know that, because you would be guaranteed to begin with same content every time.

Or if you think my workflow is incorrect and I should initialize 3rd party libraries differently, any advice would be welcomed 🙂

jiripudil commented 1 year ago

Hello, thanks for the elaborate report! I understand the problem and agree with the proposed solution. I think I'm gonna need some time to think about the implementation though. Stay tuned :)