stimulusreflex / stimulus_reflex

Build reactive applications with the Rails tooling you already know and love.
https://docs.stimulusreflex.com
MIT License
2.28k stars 172 forks source link

Reflex not binding to ajax loaded content #161

Closed acetinick closed 4 years ago

acetinick commented 4 years ago

Describe the bug

Reflex not binding to Ajax loaded content that is loaded onto page from Rails UJS remote call.

To Reproduce

Expected behavior

Reflex should bind to ajax loaded content

Versions

StimulusReflex

External tools

Browser

leastbad commented 4 years ago

Hey @acetinick! I agree that at face value, this sounds like it should work.

Could you please show us an example of the HTML being loaded by UJS?

Is anything weird showing up in the console log on the server or the client?

The other thing that would really help is a short screencast showing what's happening, including in the developer console.

Note: 3.1.3 is out. I don't think that is what's causing the bug, but it's good to be on the latest.

acetinick commented 4 years ago

Thanks mate for looking into.

This is the outputted HTML after UJS

image

The same reflex data attribute code outside of my UJS rendered modal, triggers fine.

My generic modal js code is something like this

image

No messages in console or any errors.

Sorry wrote incorrect version number of stimulus_reflex, I am actually using 3.1.3, updated original ticket.

FYI normal Stimulus controllers that I have defined in the same Ajax loaded modals, work normally.

leastbad commented 4 years ago

If you use your elements inspector to insert a new element into your page that has a data-reflex attribute on it, will it work?

My hunch is that StimulusReflex.initialize() calls setupDeclarativeReflexes for every "load" scenario except ajax:complete. I believe that this is an omission, @hopsoft.

There are a couple of potential workarounds until we can properly address this, hopefully soon.

First, you can probably import SR in your Stimulus controller and force a rescan:

import StimulusReflex from 'stimulus_reflex'
StimulusReflex.setupDeclarativeReflexes()

The other path could be to manually trigger cable-ready:after-morph on document. It's a hack, but it should work.

acetinick commented 4 years ago

Na copying and pasting the select element using inspector doesn't pick it up either after the UJS is called. Works before modal is UJS called. Weird, maybe something conflicting somewhere or as you mentioned i think it might be missing a 'ajax:complete' event listener.

I tried using setupDeclarativeReflexes() but method doesn't exist? Don't think its not exposed. Would be nice to have a public rescan method available.

leastbad commented 4 years ago

Hi again Andrew,

You are 100% correct about the setupDeclarativeReflexes method not being exported. We're looking into the best way to fix this. And it turns out that it's not UJS; any data-reflex attributes that are added dynamically are not being picked up. Believe it or not, you're the first person to notice this and it's because usually if you're adding behaviours after loading, people add data-action attributes. It seems like a silly oversight looking back.

Our plan is to make it call setupDeclarativeReflexes when ajax:complete is triggered by UJS. I agree that it should also be added to the export list.

In the meantine, after your UJS action finishes, manually emit an event like this:

document.dispatchEvent(new Event('cable-ready:after-morph'))

The above should force SR to rescan for new data-reflex attributes. Let me know how it goes!

acetinick commented 4 years ago

Yep the manually emitted event works well for a temporary solution. Thanks heaps.

Great project, excited to see where this is taking Rails with a refreshing approach to avoid SPA.

leastbad commented 4 years ago

I'm so glad you got sorted out, and thanks for the kind words.

If you feel this issue is resolved, let's close it. You should see this working without hacks in the next release.

leastbad commented 4 years ago

I'm pretty sure that this will work for you in the future, @acetinick. @darkrubyist will also be able to call StimulusReflex.setupDeclarativeReflexes() after building content with a template engine.

BodomBeach commented 3 years ago

What is the status on this issue ? I am trying to bind on a HTML element added in ajax, the reflex method is run fine, but my component is not updated. I have tried the following without any success: -document.dispatchEvent(new Event('cable-ready:after-morph')) -StimulusReflex.setupDeclarativeReflexes()

Thanks!

leastbad commented 3 years ago

@BodomBeach hey Nicolas, could you please jump on Discord? So many questions, but this is not the best medium for troubleshooting. https://discord.gg/XveN625