Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jQuery Plugins #246

Closed
matedemorphy opened this issue Jun 26, 2020 · 11 comments
Closed

jQuery Plugins #246

matedemorphy opened this issue Jun 26, 2020 · 11 comments

Comments

@matedemorphy
Copy link

Is there some additional configuration to achieve jQuery plugins works properly after a reflex is executed?. For example bootstrapSwitch.

document.addEventListener("turbolinks:load", () => { $('[data-toggle="tooltip"]').tooltip() $('[data-toggle="popover"]').popover() $("[type='checkbox']").bootstrapSwitch() })

Thanks

@RolandStuder
Copy link
Contributor

RolandStuder commented Jun 26, 2020

So the short answer is, you need two things:

The elements that have should have attached behaviour need a data-reflex-permant like:

<button  data-reflex-permanent type="button" class="btn btn-secondary" data-toggle="tooltip" data-placement="top" title="Tooltip on top">
  Hey I am tool-tipsy
</button>

The second part is, you have to also listen to another event.

So in the the application_controller.js set up the event

  afterReflex () {
    const event = new Event('stimulus-reflex:load');
    document.dispatchEvent(event)
  }

There are lifecycle events emitted by stimulus_reflex, like stimulus-reflex:after but for some weird reason, that I can't figure out, the event can be listened to, but the jQuery updates in there do not work.

Then in some controller (in connect or the application.js you can set it up like this

document.addEventListener('stimulus-reflex:load' => {
  $('[data-toggle="tooltip"]').tooltip();                   
})

So this works but it is not very elegant, as you need to use permanent, and somehow can't use the build in lifecycle events (not sure what I am missing there)

I hope this helps for the moment. I dug deeper, because personally I think we should be able to do this without data-reflex-permament

@matedemorphy
Copy link
Author

@RolandStuder Thanks for your answer i've allready has data-reflex-permant in the partials wich i don't need to be updated. I add the code you provide me but still doesn't works, in fact, not even a console.log() inside the stimulus-reflex:load event is is showing in the console, so the event is not been fired when the page updates.

@RolandStuder
Copy link
Contributor

@matedemorphy I really dived into this one. It is surprinsingly tricky, but mainly because the jQuery methods do weird things when attaching event handlers.

So did you make sure the application_controller.js is firing the afterReflex(), so it is actually triggering the event?

application_controller.js

import { Controller } from 'stimulus'
import StimulusReflex from 'stimulus_reflex'

export default class extends Controller {
  connect () {
    StimulusReflex.register(this)
  }

  afterReflex () {
    const event = new Event('stimulus-reflex:load');
    document.dispatchEvent(event)
    console.log("stimulus-reflex:load dispatched")
  }
}

btw: There is an alternative to using data-reflex-permanent which is to to take all the tooltip elements, copy the html and replace the outerHTML for each element, then do again $('[data-toggle="tooltip"]').tooltip() It is stupid. but the thing is jQuery / Bootstrap are doing weird stuff, that makes it hard to work with them. Probably overall you win more, by just writing a tooltip controller yourself with stimulus instead of trying to marry these JS utilities with Stimulus Reflex.

@matedemorphy
Copy link
Author

matedemorphy commented Jun 26, 2020

@RolandStuder it's an implementation of tabulation demo with pagy gem, the thing is this afterReflex() it's just fired when i click in the current page number, although the navigation itself it works correctly. But i think this is not just about jQuery, i'm using ActionText, and by using StimulusReflex, the textarea looses the Trix appareance.

@matedemorphy
Copy link
Author

it's normal that a console.log inside connect() prints 5 times?

@matedemorphy
Copy link
Author

i don't get it, according the docs https://docs.stimulusreflex.com/scoping#persisting-elements data-reflex-permanent should be enough. maybe some additional config is necessary

@RolandStuder
Copy link
Contributor

RolandStuder commented Jun 28, 2020

@matedemorphy do not listen to the terrible advice @RolandStuder gave to you (I am allowed to say this, as I wrote that advice)

Adding a global event and listening is kind of bad. The stimulus way, is actually much more elegant.

Just create a tooltip controller:

import { Controller } from "stimulus"
import StimulusReflex from 'stimulus_reflex'

export default class extends Controller {
    
    connect() {
        $(this.element).tooltip()
        this.element.setAttribute("data-reflex-permanent", true)
    }
}

and in you tooltip thing you make sure the tooltip element uses that controller:

<button data-controller="tooltip" title="Tooltip on top">

The cool thing about this, is that is it actually agnostic to the implementation, so you can easily change the tooltip implementation without even changing the attributes.

Just as a comment on your questions:

it's normal that a console.log inside connect() prints 5 times?

Connect get executed for every html element that has that controller, so yes, if you have 5 elements with tooltips, connect() will be executed for each html element.

I don't get it, according the docs https://docs.stimulusreflex.com/scoping#persisting-elements data-reflex-permanent should be enough. maybe some additional config is necessary

data-reflex-permament just makes sure that this html element is not morphed (changed) after a reflex. But a reflex is adding new DOM elements you have to attach event handlers to the new elements, or then use a delegated event handling (see the selector option in https://getbootstrap.com/docs/4.5/components/tooltips/#options).

This is not different to creating a new element with $('.something).append(something), new dom node, does not magically have event handlers. You need delegated events or add new events, like I do in connect()

I think this issue should be closed. If you need more support I think it is better to ask in https://stimulus-reflex.discourse.group/ as this is not really an issue of StimulusReflex.

But i think this is not just about jQuery, i'm using ActionText, and by using StimulusReflex, the textarea looses the Trix appareance.

Yeah whatever is not set to data-permanent-reflex will be changed to its original state, before any onload events. This is expected behaviour. You need to think that the reflex render the controller_action again, an then morphs the differences between the current page and the newly render page of the controller_action. So any client side changes after loading the page (as for example changing the trix appearance) get lost.

@matedemorphy
Copy link
Author

matedemorphy commented Jun 30, 2020

@RolandStuder Thanks. data-permanent-reflex it's doing well, to fix the error with Trix editor this tutotrial http://www.sweatshorts.co/ruby-on-rails/using-trix-editor-with-stimulusreflex, but for some reason sometimes the afterReflex() callback doesn't execute although the Reflex action does correctly, so it should be something in my code. But i have a doubt, i need this line in session_store.rb since is a multitenant app: Rails.application.config.session_store :cookie_store, key: _myapp_session, domain: lvh.me this can enter in conflict with Stimulus Reflex?

@RolandStuder
Copy link
Contributor

@matedemorphy As I said forget about the afterReflex. It's not a good practice for this.

And you are not giving any information so it is not possible to help you. If you want help you should put the same effort into your question as I put in my answer. Post you code, better yet, make the a repo accessible, state what you want, what you expect, what happens instead.

Also read this: https://docs.stimulusreflex.com/lifecycle#client-side-reflex-callbacks and this https://github.com/RolandStuder/til/blob/master/stimulus-reflex/lifecycle-events-only-triggered-for-corresponding-controller.md

@matedemorphy
Copy link
Author

matedemorphy commented Jul 1, 2020

@RolandStuder Sorry, and thanks for your help, but right now the class .wait in doesn't removes, so spinner it couldn't hide, take a look to this gist: https://gist.github.com/matedemorphy/94c6ad13b6aebd89862b5b14120c98df

If i put document.body.classList.remove('wait') in tabular_controller it won't hide either.

@leastbad
Copy link
Contributor

Hi @matedemorphy, I hope you got your controllers working. I'm going to close this because it's more of a support concern than an issue with the library. If you are still looking for help on it, feel free to ask on Discord.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants