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

Events are getting registered before DOM load #90

Closed
praWeb opened this issue Sep 6, 2019 · 4 comments · Fixed by #105
Closed

Events are getting registered before DOM load #90

praWeb opened this issue Sep 6, 2019 · 4 comments · Fixed by #105
Labels

Comments

@praWeb
Copy link

praWeb commented Sep 6, 2019

Please excuse me, if I am trying this whole thing wrongly.

I have followed the documentation, and followed all the steps under Usage correctly, and can see the render_async working. But when I try to use toggle event, click action is not working.

Implemented toggle as below:

<a href="#" id='detail-button'>Detail</a>

<%= render_async gift_cards_cart_transactions_path, toggle: { selector: '#detail-button', event: :click } %>

Can see the code generated as below:

 <script>
//<![CDATA[

      (function() {

  var _makeRequest = function(currentRetryCount) {
    var request = new XMLHttpRequest();
    var asyncRequest = true;
    var SUCCESS = 200;
    var ERROR = 400;

    request.open('GET', '/cart/transactions/gift_cards', asyncRequest);

    var headers = {};
    var csrfTokenElement = document.querySelector('meta[name="csrf-token"]')
    if (csrfTokenElement)
      headers['X-CSRF-Token'] = csrfTokenElement.content

    Object.keys(headers).map(function(key) {
      request.setRequestHeader(key, headers[key]);
    });

    request.onreadystatechange = function() {
      if (request.readyState === 4) {
        if (request.status >= SUCCESS && request.status < ERROR) {
          var container = document.getElementById('render_async_3d086c93961567805960');
          container.outerHTML = request.response;

        } else {
          var skipErrorMessage = false;

          if (skipErrorMessage) return;

          var container = document.getElementById('render_async_3d086c93961567805960');
          container.outerHTML = '';

        }
      }
    };

    var body = "";
    request.send(body);
  };


  var _renderAsyncFunction = _makeRequest;


  var selectors = document.querySelectorAll('#detail-button');

  [...selectors].forEach(function(selector) {
    selector.addEventListener('click', function(event) {
      event.preventDefault();
      if (_interval) {
        clearInterval(_interval);
        _interval = undefined;
      } else {
        _renderAsyncFunction();
      }
    })
  });

})();


//]]>
</script>

But the issue happening is, this piece of code is running before DOM load, which technically mean the element with id detail-button is still available on the DOM, and so no event listener is being added to it.

Is there a way to get this script executed after DOM is ready?

Thanks in advance.

@praWeb praWeb changed the title It is trying to register events even before DOM load. Events are getting registered before DOM load Sep 6, 2019
@nikolalsvk
Copy link
Collaborator

nikolalsvk commented Sep 7, 2019

Hi @praWeb, thanks for submitting an issue to render_async!

Oh, I see what's the problem. I'll try to fix this soon and ship the new version of the gem that adds event listeners after the DOM is loaded. Thank you for explaining the issue so well :)

@naveed-ahmad
Copy link

naveed-ahmad commented Sep 7, 2019

@nikolalsvk once lazy loaded is merged, I think we can simplify this as well. We don't have to add support for toggle

Simply call render_async lazy_load: true in hidden dom. And show this dom when user click on toggle. Lazy rendering could open door for lots of interesting things we can do using this gem.

@nikolalsvk
Copy link
Collaborator

nikolalsvk commented Mar 22, 2020

Hey, @praWeb! I've released 2.1.5 version of this gem that solves this issue. Can you check if it's working for you?

@vanboom
Copy link

vanboom commented May 15, 2020

@praWeb, can you post the location of content_for(:render_async) in your layout. That is where the Javascript will be injected. Are you using turbolinks?

See #108 - I am not using Turbolinks and not able to reproduce this issue with content_for(:render_async) placed at the end of my layout.

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

Successfully merging a pull request may close this issue.

4 participants