Render template having Jquery datatables in .js.erb file - ruby-on-rails

I am currently working on a project where I am implementing several reports. The report filters are remotely submitted to my action and the return results are displayed in Datatable with searching,sorting and pagination.
I have a drg.js.erb file which is having code like this :
var html = "<%= escape_javascript(render(partial: 'drg_datatable',formats: [:html],locals: {result: #result})) %>";
$("#datatable-result").append(html);
The partial _drg_datatable.html.erb is having datatable implemented like this. Below is my _drg_datatable.html.erb file :
<% if result %>
<table id="results" class="table table-striped table-bordered display">
<% case params[:view] %>
<% when "ahfs" %>
<%= datatable_ahfs_result(result) %>
<% when "drg_code" %>
<%= datatable_drg_result(result) %>
<% when "inpharmics_id" %>
<%= datatable_inpharmics_id_result(result) %>
<% when "provider" %>
<%= datatable_provider_result(result) %>
<% else %>
<% end %>
</table>
<% end %>
The problem I am facing is that when I render the partial _drg_datatable.html.erb using .js.erb file it creates the table but escapes the javascript to add sorting,pagination and other cool features we get in Jquery Datatables. Can someone point me how should I go about doing this ? I have tried to render the partial is .js.erb without writing escape_javascript but then the partial does not get rendered at all.

You must explicitly call the datatable js function in your drg.js.erb in order to "datatablize" your table. Ex:
var html = "<%= escape_javascript(render(partial: 'drg_datatable',formats: [:html],locals: {result: #result})) %>";
$("#datatable-result").append(html);
$('#results').dataTable();
I suppose you have something like:
$(document).ready(function(){
$('a selector of yours').dataTable();
});
somewhere in your application's javascripts. This runs once, after document load and applies to elements existent to your dom. Since now you are adding a new table you have to "re assign" the datatable behavior...

#grotori: Your solution gave me a hint of fixing it. I renamed my datatable id with a name which was not used in the application anywhere. I removed the initial implementation of the datatable in the partial and modified the code to render the partial first and than apply datatable to it. Here is what I did :
var html = "<%= escape_javascript(render(partial: 'drg_datatable',formats: [:html],locals: {result: #result})) %>";
$("#datatable-result").html(html);
jQuery(function() {
$("#drg-results").dataTable({
"sDom": "<'row-fluid'<'span4'l><'span7 pull-right'f>r>t<'row-fluid'<'span4'i><'span7 pull-right'p>>",
"sPaginationType": "bootstrap",
"sScrollX": "100%",
"bDestroy": true,
"bProcessing": true,
"bScrollCollapse": true
});
});
Hope this helps other trying to achieve the same thing.

Related

Ruby on Rails app glitching when Chrome auto complete is being used

I have a weird bug that hangs up or makes my app unusable or freezes for a minute.
So I have a 2 forms side by side one for billing and one for shipping and it has a drop down that uses the select2 library. When a user selects this drop down the Chrome autocomplete shows up too. It's overlapping the select2 dropdown. Here's an image:
So the problem here is when the user uses that drop down to select a country and uses the Chrome autofill instead of the select2 drop down and hits the enter key the form on the right fills the country and hangs up or freezes the app. Also when they choose a country or a state it will do a get request to the server.
What I tried are:
turn off the Chrome autocomplete on the settings; it works with no issues. The form on the right won't be updated (so I concluded it was Chrome)
I added an html: {autocomplete: 'off'} but this doesn't work, and I don't know why.
Here's the form:
<%= form_for [:admin, #corporate_account], html: { autocomplete: "off" } do |f| %>
<fieldset data-hook="new_property">
<div class="row">
<div class="col-md-12">
<%= render partial: 'form', locals: { f: f } %>
</div>
</div>
</div>
<div class="col-md-12">
<%= render partial: 'address_form', locals: { f: f } %>
</div>
</div>
<div class="form-actions">
<%= render partial: 'spree/admin/shared/new_resource_links' %>
</div>
</fieldset>
<% end %>
Update
I found that when I hit the enter with the Chrome autocomplete it sends a GET request, but with the regular drop down from the app it doesn't. I think Chrome's autocomplete after hitting the enter key it sends the form.
We are using select2 for our searches. It uses jQuery and ids are dynamically added. I found the script attaches the ID dynamically. It wasn't in the .js file, it was inside the .erb file. I've added this .js script inside the .erb file.
<% content_for :head do %>
<%= javascript_tag do %>
$(document).ready(function(){
$('span#<%= s_or_b %>country .select2').on('change', function() { update_state('<%= s_or_b %>'); });
<%# bellow this comment the code that I added %>
<%# this IDs are gnerated dynamically by select2 %>
const countryID = $('span#<%= s_or_b %>country .select2 .select2-search input').attr('id')
const stateID = $('span#<%= s_or_b %>state .select2 .select2-search input').attr('id')
<%# add the type attribute search so autocomplete can be toggled on and off %>
$(`#${countryID},#${stateID}`).attr('type', 'search')
<%# on focus set the autocomplete attribute off %>
$(`#${countryID},#${stateID}`).on('focus', function(){
$(`#${countryID},#${stateID}`).attr('autocomplete', 'off')
})
});
<% end %>
<% end %>
So when I focus on the search input, Chrome's autocomplete is not working any more.

Want to add dynamic list with dynamic data through js

There is a main file in which i want to add li in ul with dynamic value.
<ul class="selected_questions"></ul>
In my js.erb i want to show title. I have debugged it and #ques value is there but not showing in ul. Following is my code.
<% if #ques.errors.any? %>
console.log('Error');
$('#dialog-form').html('<%= escape_javascript(render('form')) %>');
<% else %>
console.log('Created');
$(".selected_questions").append('<li><span class="tab">"'+#ques.title+'"</span></li>');
$('#dialog-form').dialog('close');
$('#dialog-form').remove();
<% end %>
I also have tried following way :
$('<li />', {html: #ques.title}).appendTo('ul.selected_questions')
Simple string is appended successfully but object from controller not been shown. What am i doing wrong ???
Try this
change this
$("#selected_questions").append('<li><span class="tab">"'+#ques.title+'"</span></li>');
to
$("#selected_questions").append('<li><span class="tab"><%= #ques.title %></span></li>');

Reloading page partially in Rails

I'm developing a music website in Rails. The landing page is divided and has a search form where you can look up bands stored in the DB. Inside the other division I embedded a player reproducing some random videos. I want the search results being displayed on the same landing page.
When I submit the form the page reloads and the player reloads also and starts playing a different video. What I actually want to achieve is that the player doesn't get interrupted while the search form is submitted.
Don't know if and how this is possible the way I want it. If I got it right this link describes one way to do that but I didn't get it to work.
home controller
def index
#bands = Band.search(params[:search]).order("name ASC")
#random_band = Band.order("RANDOM()").limit(1)
end
def preview
#bands = Band.search(params[:search]).order("name ASC")
render :partial => 'preview', :content_type => 'text/html'
end
_preview.html.erb
<table class="table"
<tr>
<th>Title</th>
<th>Year</th>
</tr>
<% #bands.each do |f| %>
<tr>
<td>
<%= f.name %>
</td>
</tr>
<% end %>
</table>
home#index
<!DOCTYPE html>
<html lang="en">
<form class="navbar-form navbar-left" role="search">
<%= form_tag({:action => 'preview'}, id: "search-form", :remote => true, :'data-update-target' => 'update-container') do %>
<%= text_field_tag :search, params[:search], placeholder: "Search Bands" %>
<%= submit_tag "Search" %>
<% end %>
</form>
<div class="row">
<div class="col-md-6">
<div id="update-container">
<%= #random_band.first.name %>
</div>
</div>
<div class="col-md-6">
<%= video_tag("#{#random_band.first.name}.mp4", size: "460x390",
controls: true, autobuffer: true, autoplay: true) %>
</div>
</div>
</html>
application.js
$(function() {
/* Convenience for forms or links that return HTML from a remote ajax call.
The returned markup will be inserted into the element id specified.
*/
$('form[data-update-target]').live('ajax:success', function(evt, data) {
var target = $(this).data('update-target');
$('#' + target).html(data);
});
});
First problem: The form doesn't seem to find the preview action.
Second problem: If I change the content of the index with the preview action it does find the preview action obviously but it doesn't render the search results inside the update-container. Instead it renders them as a whole new page.
By the way, I know my way around Rails a bit but I've got absolutely no experience with Ajax.
You got most of your code very twisted and not really lean as far as I can tell. The short and very lean way to get your search results updated without reloading the rest of the page (including your player) could look like this. The index function should look like this:
//bands_controller.rb
def index
#bands = Band.search(params[:search])
end
You have to create the search-method inside of your Band-Model:
//Band.rb
def self.search(search)
if search
find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
find(:all)
end
end
You need to render your _preview.html.erb inside a div with a certain ID somewhere inside your view:
<div id="bands"><%= render 'preview' %></div>
Your form_tag has a lot of arguments that you won't need anymore:
<%= form_tag bands_path, :method => 'get', :id => "search_form" do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
<% end %>
The jquery I use for my forms looks like this.. Pretty simple in my opinion:
$(function() {
$("#search_form input").keyup(function() {
$.get($("#search_form").attr("action"), $("#search_form").serialize(), null, "script");
return false;
});
});
This fires the index.js.erb (you will have to create that) everytime you put a letter into your search field:
//index.js.erb (same folder as index.html.erb)
$("#bands").html("<%= escape_javascript(render("preview")) %>");
This should refresh your div. It's maybe a little work but that's the easiest way to implement an ajax search function into your index page that I could think of.
Sources:
Railscast#27
Railscast#240

Changing data stored in a div using ajax and ruby on rails

Does anyone know a good guide or example for me to follow on how to change data on the screen using ajax?
I have a div that stores the last #event_status and every 5 minutes I want to go get the last event status created and display it in the div using ajax.
<div id="last_status">
Last Status:
<% if #event_status.present? %>
<span id="last_status_content">[<%= #event_status.user.initials %> # <%= #event_status.created_at.strftime("%I:%M%p") %>]<br />
Audio: <%= #event_status.audio ? 'Good' : 'None' %> |
Video: <%= #event_status.video ? 'Good' : 'None' %> |
<% if #event_status.notes.present? %>
Notes: <%= #event_status.notes %>
<% else %>
Notes: No Notes
<% end %>
</span>
<% else %>
<span id="last_status_content">None</span>
<% end %>
</div>
You can use javascript to periodically call an action and place the contents into a div. First extract the content of your last_status div to a partial, then return said partial from a controller action.
Javascript in your page:
$(document).ready(
function() {
setInterval(function() {
$('.last_status').load('/controller_name/action_name');
}, 36000);
}
);
Your controller action needs to then initialize all variables used by the partial, then render the partial.
def my_action
#event_status = get_latest_event
render :partial => 'my_partial'
end

Rails - how to insert/render a file inside a View

in index.html.erb, I would like to know how to insert index.js.erb, something like:
<script type="text/javascript">
$(function() {
<%= render =>"home/index.js.erb" %>
});
</script>
Any ideas on how to just insert the index.js.erb file ?
thanks
<%= File.read "#{RAILS_ROOT}/app/views/home/index.js.erb" %>
Set your file as a partial and append preprend or do what you wana do with it.
For a partial file named _index.js.erb located in the same folder of where the file with this code is called will be prepend in the DOMID exemple.
jQuery('#exemple').prepend("<%= escape_javascript(render(:partial => 'index')) %>");
Maybe you can do a html file with it...
<% javascript_tag do %>
<%= render :partial => 'index' %>
or direct code
<% end %>

Resources