Closed jabbett closed 5 years ago
Hey @jabbett, thanks for creating this issue.
It seems like a new feature :D
I love the idea of being able to call render_async on click or another event. We could implement this feature to listen to a certain event, and after that event is dispatched, render_async logic would be called. You could, for example, pass in an element ID to render_async call and then we would listen to click (or whatever) event like this:
document.getElementById("element-ID").addEventListener("event-name", performRenderAsyncLogic)
A call to render_async could look something similar to this:
# toggle_element_id: ID of your button
# toggle_event_name: would default to "click", but you could pass whatever you wanted here
<%= render_async comment_stats_path, toggle_element_id: "my-button", toggle_event_name: "click" %>
How does this sound?
@nikolalsvk Thanks for your response!
I like your approach for something like a set of tabs that loads an object's sub-items, i.e. don't load a the "comments" tab content until the user clicks into it.
In a situation where I have a dynamic set of links, any of which could load their destination's content into the same element, what about using a link-driven approach?
<div id="message-navigation">
<% @messages.each do |message| %>
<%= link_to_async message.subject, message_path(message), replace: "#message-container" %>
<% end %>
</div>
<div id="message-container">
Click any message to display it here.
</div>
I understand that introducing a second method beyond render_async
might be beyond the scope of the project, but I hope it doesn't hurt to ask ;)
Oh OK, now I get it :)
You are trying to render content to the same container, you are "replacing" content of one container by clicking on different links if I'm correct.
We could add another method that could be called render_async_trigger
or trigger_render_async
. It could look something like this:
# you would have to set a class that will show a element as link
# since we would leave out the href empty so it doesn't refresh the page
# or we could use event.preventDefault() and pass href in options below
<%= html_element_options = { class_name: 'link' } %>
<div id="message-navigation">
<% @messages.each do |message| %>
<%= render_async_trigger "#message-container",
message_path(message), # path to load
# this will create a element
html_element_name: 'a',
html_element_options: html_element_options %>
<%= message.subject %>
<% end %>
<% end %>
</div>
<div id="message-container">
Click any message to display it here.
</div>
Which would render in HTML like:
<div id="message-navigation">
<a class="link" id="render_async_trigger_123">
First message
</a>
<a class="link" id="render_async_trigger_1234">
Second message
</a>
</div>
<div id="message-container">
Click any message to display it here.
</div>
...
<script>
// listen for #render_async_trigger_123 element click and then load defined path to #message-container
</script>
<script>
// listen for #render_async_trigger_1234 element click and then load defined path to #message-container
</script>
This will make it more usable if someone wants to render a div that needs to trigger render_async for example. In your example, we would narrow element choice to tag with link_to_async
name, so that's why I changed the name of the method and expanded it a bit :)
What do you think of this approach?
Great!
(I solve the link styling issue by using href="javascript:void(0);"
- typically less effort than duplicating all the CSS styles that need to be applied to links and their pseudo-classes.)
Come to think of it, I'd assume the most common case will be using this as a link. At the least, could we make the default behavior of render_async_trigger
use an element of a
with options of { href: "javascript:void(0);" }
, and then these can be overridden by the developer? To me, this feels more in the spirit of Rails ;)
Awesome, I'll implement this feature then :)
I just can't agree with putting href="javascript:void(0);"
inside the gem since it's obtrustive JavaScript (see Unobtrusive JavaScript). I do agree that it's more in the spirit of Rails by making you write less code, but I don't find it a good practice :(
Also, the main role of <a>
tag is to show links in HTML or link to content on page. We often bypass this by either doing what you suggested, or putting href="#"
, or the CSS class to make it a link without href attribute set. Maybe in your case it's better to convert <a>
tags to <button>
tags or make those links point to #message-container
div element.
In that spirit, I would replace <a>
with <button>
element in the previous comment and put it like that in the docs.
What do you think of this? If you have any ideas or suggestions, please let me know, don't be discouraged by this comment 😄
I think I have a similar issue to this as well... I have a table that is rendered using this gem (each row actually) and I have a bunch of filter checkboxes that a user can click with makes a remote call to a controller to filter this list based on the criteria.
Call to the controller is getting the correct number of items based on the filter ( I know this based on the placeholders rendered) but it never actually renders the content.
Here's a short video showing the issue: https://screencast.com/t/r9fYJPcqyW
@sqlninja thanks for commenting! You would definitely benefit from this feature too :)
I'll see to implemenet this, sounds and looks really cool 🍰
@nikolalsvk so I only see this issue when I have one async request (ajax and/or remote: true) attempt to render_async after success... Could you shed any light on what is (or isn't) happening for my edification?
@sqlninja could you explain further how you're using render_async in your case? Maybe it's related to https://github.com/renderedtext/render_async/issues/70 if you're trying to call render_async in the response of the filtering request.
Fix for that would be to switch over to jQuery part of the gem, which is explained in the Configuration part of the README.
I'll add a full write up of my use case on Monday, but as for simply using jQuery, that didn't work and actually introduced a new issue.
The new issue was that the html_element_name
was not being utilized.
As you may have noticed in my video, I am rendering each row asynchronously, so I render a tr
element. Although when using jQuery it just rendered the contents of the partial, which is this case was all the td
elements
@nikolalsvk sorry, forgot to add my use case:
I have a table where we load each row using render_async from the index method (we pass an array of ids to lookup each row record)
we also render_async a list of filter checkboxes
before adding render_async, the table was loaded in one fail swoop and clicking on the filter checkboxes would make an ajax call to "search" for records that match the filter and just reload the table.
Now that render_async is in place the rows render fine, but when the ajax call happens from clicking a filter the controller is called and the records attempt to load but the individual record lookup never happens.
so basically an ajax call is made to get the list of ids and then attempts to render the rows, but the render_async call is not firing.
That being said, are you at a point of being able to provide an estimated timeframe for the fix? Do you know that the issue is? Is it an issue with dynamic element js calls? Can you point me in a direction to possible help with a resolution, where should I look in the codebase?
Thanks for this gem by the way, it has sped up page load significantly...
John
Also, just tried adding an event name to see if it is ever emitted after an ajax request and it isn't...
Hey @sqlninja, could you open a new issue with your problem there so that we no longer post in this thread. It seems like a whole another problem, and this issue is about a new feature :)
I can post a possible solution to a new issue 🍰
Well in lieu of the potential new feature, I just removed the ajax calls and let the js do a redirect instead, and all is working...
Hey y'all, I've released version 2.1.1 which solves this issue!
If you have time, please try it out and see if it brings any bugs with it, thanks 🍰
I use
render_async
widely in my application, so I can get initial page load to be very fast, and then load each sub-component individually.I'd also like to be able to load new page sub-components asynchronously when a user, for example, clicks on a button.
In the past, I've tried the rails-ujs method of
link_to
withremote: true
, but this requires extra JavaScript code -- not as seamless or easy asrender_async
.Any recommendations?