Rails - Render each do block in js partial - javascript

How can I render a `.each do block in a js partial in Rails?
In my messages.js.erb file, I currently have:
<% #conversations.each do |convo| %>
<%= j render "message_listing", convo: convo %>
<% end %>
$('#conversations-body-container').append(
// APPEND RESULTS OF PREVIOUS .EACH DO RENDER
);
How can I go about appending the first block of code in my HTML using j render?

You could do like below:
<% #conversations.each do |convo| %>
$('#conversations-body-container').append('<%= j render "message_listing", convo: convo %>');
<% end %>
Or
<% #conversations.each do |convo| %>
$('<%= j render "message_listing", convo: convo %>').appendTo('#conversations-body-container');
<% end %>

Related

Rails will_paginate endless scroll with an array that drops the first 3 items

I have a partial where I'd like to drop or not show the first three articles in the array because they are in a featured articles section. I also want the partial to use will_paginate w/ endless scrolling to load the next page of articles. The issue I'm facing is that when using #articles.drop(3).each do |a| and the next page goes to load, the array drops the next three articles again.
What's the best way to solve for this? My initial thought was an array within an array, where the first array drops the first 3 then the nested array returns all articles but I'm not sure how to do that?
Array code in partial:
<% #articles.drop(3).each do |a| %>
<%= link_to a.source_url, :class => "flexRow" do %>
<%= a.source %>
<h3><%= a.title %></h3>
<% end %>
<% end %>
Index.js.erb
$('#article-index').append(' <%= j render("articles") %>');
<% if #articles .next_page %>
$('.pagination').replaceWith('<%= j will_paginate(#articles, :previous_label => '', :next_label => '', :page_links => false) %>');
<% else %>
$('.pagination').remove();
<% end %>
Index.html.erb
<div id="article-index">
<%= render 'articles' %>
</div>
UPDATE
This solution seems to work but doesn't feel elegant?
<% (#articles.current_page == 1 ? #articles.drop(3) : #articles).each do |a| %>
Try
#articles[3..#articles.count]
This will drop the records held at index 0, 1 and 2, and return the remaining.
You may do the following in your controller:
EXAMPLE
#articles = Article.where(...).paginate(page: params[:page], per_page: 10)
# Works only for the first HTML request
unless request.xhr?
#articles.shift(3)
end
.
.
.
respond_to do |format|
format.html
format.js
end
Now, when you iterate over #articles, it would start from index 3, only for first time.
EDIT
<% (request.xhr? ? #articles : #articles[3..10]).each do |a| %>
<%= link_to a.source_url, :class => "flexRow" do %>
<%= a.source %>
<h3><%= a.title %></h3>
<% end %>
<% end %>
Assuming the page size is 10.

ruby if statment for js.erb file

Could anyone assist me in setting up my js.erb file to cover two scenarios.
At the moment i have infinite scroll working when the page initially loads, but when i change the params the new collection loads fine but when i scroll down the page to load the rest of the results i just get the next set of 6 objects replacing the last, rather than appending them onto the end
rehome.js.erb
$('.all_animals').append("<%= j render #animals %>");
<% if #animals.next_page %>
$('.pagination').replaceWith('<%= j will_paginate #animals %>');
<% else %>
$(window).off('scroll');
$('.pagination').empty();
<% end %>
Javascript
function infiniteScroll() {
if($('#infinite-scrolling').size() > 0) {
$(window).on('scroll', function(){
//Bail out right away if we're busy loading the next chunk
if(window.pagination_loading){
return;
}
more_url = $('.pagination a.next_page').attr('href');
if(more_url && $(window).scrollTop() > $(document).height() - $(window).height() - 50){
//Make a note that we're busy loading the next chunk.
window.pagination_loading = true;
$('.pagination').text('Loading.....');
$.getScript(more_url).always(function(){
window.pagination_loading = false;
});
}
});
}
}
So on page load i call the function
$(function(){
infiniteScroll();
});
and as a ajax success callback
success: function(data) {
infiniteScroll();
}
When the ajax call is made the params :rehomed are always present so i could wrap the separate logic in
<% if params[:rehomed].present? %>
<% end %>
does anyone have any ideas for dealing with the newly loaded content in my rehome.js.erb file
Thanks
Update
So on page load i need this to be the logic
$('.all_animals').append("<%= j render #animals %>");
<% if #animals.next_page %>
$('.pagination').replaceWith('<%= j will_paginate #animals %>');
<% else %>
$(window).off('scroll');
$('.pagination').empty();
<% end %>
and when an update is made to the collection i need
$('.all_animals').empty();
$('.all_animals').append("<%= j render #animals %>");
<% if #animals.next_page %>
$('.pagination').replaceWith('<%= j will_paginate #animals %>');
<% else %>
$(window).off('scroll');
$('.pagination').empty();
<% end %>
How to combine them into one statement is what im trying to work out

Nested .each on embedded ruby not printing anything

I'm having some problems with embedded ruby. I'm trying to iterate through some variable, to print some JavaScript code.
This is the following code:
<% color1 = '#ff0000' %>
<% color2 = '#00ff00' %>
<% color3 = '#ffff00' %>
<% i = 0 %>
<% j = 0 %>
<% #chapters.each do |chapter| %>
sigInst.addNode('cap<%= chapter.reference %>',{
label: 'cap <%= chapter.reference %>',
color: '<%= j%2==0 ? color1 : color2 %>',
x: <%= i = i %>,
y: <%= i = i %>
}).draw();
<% i = i + 0.1 %>
<% j=j+1 %>
<% end %>
<% #chapters.each do |chapter| %>
<% chapter.decisions do |decision| %>
sigInst.addEdge('cap<%= chapter.reference %>_cap<%= decision.destiny_num %>','cap<%= chapter.reference %>','cap<%= decision.destiny_num %>').draw();
<% end %>
<% end %>
I'm using Sigma js to implement a graph. The first .each appears in the view, but the second part doesn't print anything. What's happening? Thanks
You forgot to do a .each on your decisions.
So the fixed line would be: <% chapter.decisions.each do |decision| %>
Ruby has the sometimes annoying feature of allowing you to pass a block to anything, whether it uses it or not. So in this case, you're just passing the block to the decisions method, which does nothing with it.

Rails 3 javascript: How to render a partial with parameters

I'm still getting the hang of Rails. Here I'm using Rails 3 and the goal basically is to have an AJAX call triggered when I click the subscribe button the post_form partial is rendered beneath for the topic I have just subscribed to. The button then becomes an unsubscibe button and the post_form partial is removed. The toggling of the button alone works (i.e: by removing the second line in the two immediately following snippets), but the rendering of the *post_form* partial does not.
The problem is I can't seem to get the right syntax and/or passing of parameters in the two following partials. The topic object is just not passed and I get an invalid model_name for NilClass error when clicking on the subscribe or unsubscribe button. If I refresh the page manually, the partial is rendered or hidden the correct way, so it's really just the AJAX part that isn't working right.
views/subscription/create.js.erb
$("#subscription_form").html("<%= escape_javascript(render('users/unsubscribe')) %>");
$("#post_form").html("<%= escape_javascript(render('shared/post_form', :topic => #topic)) %>");
views/subscription/destroy.js.erb
$("#subscription_form").html("<%= escape_javascript(render('users/subscribe')) %>");
$("#post_form").html("<%= escape_javascript(render('shared/post_form', :topic => #topic)) %>");
views/users/_subscription_form.html.erb
<% unless current_user?(#user) %>
<div id="subscription_form">
<% if current_user.subscribed?(#topic) %>
<%= render 'users/unsubscribe', :topic => #topic %>
<% else %>
<%= render 'users/subscribe', :topic => #topic %>
<% end %>
</div>
<% end %>
controllers/subscriptions_controller.rb
class SubscriptionsController < ApplicationController
before_filter :signed_in_user
respond_to :html, :js
def create
#topic = Topic.find(params[:subscription][:topic_id])
current_user.subscribe!(#topic)
respond_with #topic
end
def destroy
#topic = Subscription.find(params[:id]).topic
current_user.unsubscribe!(#topic)
respond_with #topic
end
end
views/shared/_post_form.html.erb
<%= form_for(#post) do |f| %>
<div class="field">
<%= f.hidden_field :topic_id, :value => #topic.id %>
<%= f.text_area :content, placeholder: "Tell us about it ..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
If it is of any help, the relationships are:
post -> belongs_to -> topic and topic -> has_many -> posts
Looks like you're using the variable "#post" in the "views/_post_form.html.erb" file.
<%= form_for(#post) do |f| %>
Since you aren't setting that variable anywhere in your actions you would get a null reference error.
You would need to do something like this:
def create
#post = Post.find(the_post_id)
#topic = Topic.find(params[:subscription][:topic_id])
current_user.subscribe!(#topic)
respond_with #topic
end
Also you are passing in the "topic" variable as a local but accessing it as an instance variable. You should change the your _post_form.html.erb file to look like this:
<%= form_for(#post) do |f| %>
<div class="field">
<%= f.hidden_field :topic_id, :value => topic.id %>
<%= f.text_area :content, placeholder: "Tell us about it ..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
I don't have my ruby environment readily available so I can't verify that this will solve your problem but I think it should move you in the right direction.

How can I return javascript from a Ruby on Rails helper method?

I have a Note model, which can contain have either an image link attachment (linktype = "image" or some text (linktype = "text). When I display the notes, the method of display changes depending on the linktype. An example is:
<% #notes.each do |q| %>
<h2 class="title"><%= q.name %></h2>
<% if q.linktype == "other"%>
<script type="text/javascript">some javascript</script>
<% elsif q.linktype == "text"%>
<%= q.text %>
<% elsif q.linktype == "image"%>
<img src="<%= q.link %>" />
<% end %>
<% end %>
I have to display the notes in a few different views in my site, so rather than have to repeat the viewing code multiple times, I want to have it in one place and refer to it from different views.
My initial thought was to put the display code in a helper, something like this:
<% #notes.each do |q| %>
note_display(q.linktype, q.link)
<% end %>
But some of the displaying involves javascript (line 4 in first code block). Can I still use a helper method, even though I would need it to return javascript? If so, how do I do it? Thanks for reading.
There's nothing special about javascript, you can return it from helpers as you would return other html content. The only thing I would suggest is to use helpers for tags like
image_tag(q.link)
javascript_tag("some javascript")
content_tag("h2", q.name, :class => "title")
As far as ERB is concerned, JavaScript is just string content like anything else rendered by a template. So your helper method can just construct and return a string:
def note_display(note)
content = ''
content << content_tag('h2', h(note.name), :class => 'title')
if note.linktype == 'other'
content << javascript_tag("some javascript")
elsif note.linktype == 'text'
content << h(note.text)
elsif note.linktype == 'image'
content << image_tag(note.link)
end
content
end
You can use this helper method using:
<% #notes.each do |n| %>
<%= note_display(n) %>
<% end %>

Categories