How to call a .js.erb file instead of a .rjs one - javascript

I'm working on a migration from Prototype to jQuery and we also have to remove .rjs file when we can. There is here one issue :
I have got the update_overall_comment.rjs file in the app/views/results folder:
page.replace 'overall_comment', :partial => 'results/marker/overall_comment', :locals => {:result => #result}
page.visual_effect(:highlight, 'overall_comment_text_area', :startcolor => '#BDFCC9')
The _overall_comment.html.erb file in the app/views/results/markers folder:
<div id="overall_comment">
<div id="overall_comment_edit">
<%= form_for #result,
:remote => true,
:url => { :action => 'update_overall_comment', :id => #result.id } do |f| %>
<%= f.text_area :overall_comment,
:cols => 50,
:rows => 5,
:id => 'overall_comment_text_area',
:onkeydown => "$('overall_comment_submit').enable();" %>
<div>
<%= f.submit t(:save_changes),
:disable_with => I18n.t('working'),
:disabled => true,
:id => "overall_comment_submit"%>
</div>
<% end %>
</div>
</div>
And the results.controller.rb file (I just show the relevant function ) in the app/controllers folder:
def update_overall_comment
#result = Result.find(params[:id])
#result.overall_comment = params[:result][:overall_comment]
#result.save
end
The fist thing I would like to understand is how to transform the .rjs file to a .js.erb on. I removed it and created update_overall_comment.js.erb (in the same folder) which only contains a console.log('...'), and I never saw the console.log called.
Do you have any ideas ?
Thank you in advance.

rename update_overall_comment.rjs to update_overall_comment.js.erb
then in this file:
$('#overall_comment').html("<%= j(render 'results/marker/overall_comment') %>");
$('#overall_comment_text_area').effect("highlight", { color: "#BDFCC9" }, 3000);
p.s. not sure about the highlight, also for verifying that the js.erb file is called/rendered, I use alert('something here'); instead of console('...');, but this shouldn't be much of a difference in order to test an ajax call.

Thank you very much. I have made some mistakes.
For instance I thought a line with "//" was a comment and in fact it does a ajax error. Also I used partial for the first line and it did't work.
And I thought this js.erb file would inform me about errors but no. It just stop when it doesn't work without any information. So I had to find by myself that my jquery version didn't have the "effect" method.
But now it works and your translation of visual_effect work (I just put 1000ms instead of 3000).

Related

Rails/Javascript: Data attribute not returned through partial, but present in DOM

I am trying to display the value of a select field for shipping costs beneath the field. Thanks to #Vasfed I am tying to use data attributes and javascript. But while the data attribute is rendered in the DOM while loading th page it is not returned in the data returned for the AJAX call when inspecting console or resources.
In DOM:
<select id="shippingservices_select" name="cart[shippingservice_id]"><option value="">select a carrier</option>
<option value="7" data-price="3.9">UPS</option>
<option value="19" data-price="10.0">DHL</option>
</select>
The fetched partial:
$("#shippingservices_select").empty()
.append("<option value=\"7\">UPS<\/option><option value=\"19\">DHL<\/option>");
I am using the following ajax call:
$(document).on("change", "#lands_select", function(event){
jQuery.ajax({
url: "/carts/update_shipping/" + event.target.value,
type: "GET",
error: function (xhr, status, error) {
console.error('AJAX Error: ' + status + error);
},
success: function (response) {
console.log(response);
}
});
});
Which should return both value and data attribute, for the form:
<%= form_for :cart, :url => {:action => "show_shipping"}, :html => { :method => "get", :remote => true } do |f| %>
<%= f.collection_select(:land_id, Land.all, :id, :name, {:prompt => "select a country"}, {:id => 'lands_select'}) %><br>
<%= f.select(:shippingservice_id, options_for_select(#shippingservices.collect { |s| [s.name.titleize, s.id, {'data-price' => s.price}] }), {:prompt => "select a carrier"}, {:id => 'shippingservices_select'}) %><br>
<% end %>
Shipping: €<div id="shipping_cost"></div><br>
with the update_shipping.js.erb view:
$("#shippingservices_select").empty()
.append("<%= escape_javascript(render(:partial => #shippingservices)) %>");
and the rendered partial _shippingservice.html.erb of:
<option value="<%= shippingservice.id %>" data-price="<%= shippingservice.price %>"><%= shippingservice.name.titleize %></option>
In the controller I have:
def update_shipping
...
respond_to do |format|
format.js
end
end
Following my partial _shippingservice.html.erb I should get both value and data attribute, but I do not. I think this is the reason why:
$(document).on("change", "#shippingservices_select", function(event){
var price = $(event.target).data('price');
$("#shipping_cost").html(price);
});
Does not return the value of data-price.
How can I get this to work? Thank you in advance.
UPDATE
I was trying to troubleshoot it and things appear to be quite strange.
Both selectors display data in the DOM. The shipping service select field which get’s loaded on page load shows everything. On changing the land selector, the partial which gets loaded and which I can inspect in console does only display option value + name, but when changing the _shippingservice partial I found out that the code which gets loaded through AJAX appears not to be generated by the partial referenced in the JS Ajax call, since I can change the code inside without producing any effect on the delivered payload.
But when substituting
<%= escape_javascript(render(:partial => #shippingservices))%>
By
<%= escape_javascript(render ‘carts/shippingservice’)%>
Nothing is displayed and loaded.
You can check what partials are getting rendered on the terminal where you are running rails. Looks like you have more than 1 possible partial for shipping services.
You can also specify which partial to use instead of letting rails guess:
render partial: 'carts/shippingservice', collection: #shippingservices, as: :shippingservice

Making tinyMCE and Garlic.js work together

I'm trying to make Garlic.js and tinyMCE work together in my Rails app without success. I've integrated Garlic in my asset pipeline and for tinyMCE I'm using tinymce-rails gem.
Both work great separately but when I put them together Garlic stops working.
I've recently tried micschk's potential solution posted in Garlic's github repository https://github.com/guillaumepotier/Garlic.js/issues/87 which involves initialising tinymce with the following code:
views/layouts/application.html (following script inside head tag)
<script>
tinyMCE.init({
selector: 'textarea.tinymce',
setup : function(editor) {
editor.on("change keyup", function(e){
console.log('saving');
tinyMCE.triggerSave(); // updates all instances
// editor.save(); // updates this instance's textarea
$(editor.getElement()).trigger('change'); // for garlic to detect change
});
}
});
</script>
the code does initialise tinymce and runs the code after 'setup' but it does not seem to make Garlic work.
Here's my view code for reference
<%= simple_form_for(#open_ender, remote: true, html: {"data-persist" => 'garlic', id:'open_ender_form' }) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :answer_id, :required => true, :as => :hidden, :autofocus => true, input_html: {value: #answer.id } %>
<%= f.input :content, :input_html => { :class => 'tinymce' }, :label => false, :required => true, :autofocus => true %>
<%= button_tag(type: 'submit', id: "save-btn", style:'background:transparent' ) do %>
<i class="fa fa-floppy-o" aria-hidden="true" title="save"; data-toggle="tooltip"; data-placement="right"></i>
<% end %>
</div>
<% end %>
I would really appreciate if someone could point me to the right solution.
I've finally decided to use the tinyMCE autosave plug-in instead of using Garlic.js although the functionality is not exactly the same it serves the purpose of protecting users from losing their data.
https://www.tinymce.com/docs/plugins/autosave/

Rails Ajax Refresh Partial while persisting params

I have a Rails app with a controller/view called "calls". Here is the basic controller action for index:
calls_controller.rb
def index
if params[:region].present?
#assigned = Call.where(region_id: params[:region][:area]).assigned_calls.until_end_of_day
#unassigned = Call.where(region_id: params[:region][:area]).unassigned_calls.until_end_of_day
else
#assigned = Call.assigned_calls.until_end_of_day
#unassigned = Call.unassigned_calls.until_end_of_day
end
end
Here are my views:
index.js.erb
$('#active').html("<%= escape_javascript render :partial => 'calls/assigned_calls', :locals => {:assigned_calls => #assigned} %>");
$('#inactive').html("<%= escape_javascript render :partial => 'calls/unassigned_calls', :locals => {:unassigned_calls => #unassigned} %>");
$(".select").select2({
placeholder: "Select One",
allowClear: true
});
index.html.erb
<div id="active">
<%= render "assigned_calls" %>
</div>
<div id="inactive">
<%= render "unassigned_calls" %>
</div>
<script>
$(document).ready(function() {
setInterval(function () {
$.ajax('calls/<%= params[:region][:area] %>');
} , 5000);
});
</script>
_assigned_calls.html.erb (view code omitted)
<%= form_tag calls_path, :method => 'get' do %>
<p>
<%= select_tag "region[area]", options_from_collection_for_select(Region.order(:area), :id, :area, selected: params[:region].try(:[], :area)), prompt: "Choose Region" %>
<%= submit_tag "Select", :name => nil, :class => 'btn' %>
So what's happening is on page load if I do not have the params of :region passed it sets the calls without being scoped by region. If region_id is present then it scopes calls where region_id is "1" or whatever the Region ID is that is passed from the submit_tag.
This works fine in the controller and view, however here's my problem. My index.html.erb I need to refresh the partials WITHOUT disturbing the params passed. So on setInterval I need to figure out how to reload the partials while persisting the params passed in the URL.
I tried to figure this out using a setInterval method but I'm not sure what I'm doing here 100%.
Can someone give me some advice on how to refresh the partials every 5 seconds while persisting the params so my instance variables persist through refresh?
If you need more context and/or code please let me know.
Update
Trying to rework the javascript based off an answer from a user and here's what I have.
<script>
$(document).ready(function() {
setInterval(function () {
$.ajax({
url: 'calls_path',
type: "GET",
data: { "region": '<%= #region.html_safe %>' }
}), 5000);
});
});
</script>
The page will load but when it tried to trigger in the chrome inspector I get:
calls?utf8=✓&region[area]=3:2901 Uncaught SyntaxError: Unexpected token )
Maybe this is a JS syntax error or I'm not closing the function properly.
If I understood properly, you want to have your parameters somehow pipelined through AJAX call to your controller, back to your js.erb file where it refreshes the partials?
My advice is to set passed parameters as instance variables in your controller like this:
calls_controller.rb
def index
if params[:region].present?
#region = params[:region]
#assigned = Call.where(region_id: params[:region][:area]).assigned_calls.until_end_of_day
#unassigned = Call.where(region_id: params[:region][:area]).unassigned_calls.until_end_of_day
else
#assigned = Call.assigned_calls.until_end_of_day
#unassigned = Call.unassigned_calls.until_end_of_day
end
end
Now your #region instance variable will be available in your index.js.erb
where you can pass it to other partials you are trying to render.
index.js.erb
$('#active').html("<%= escape_javascript render :partial => 'calls/assigned_calls', :locals => { :assigned_calls => #assigned, :region => #region } %>");
$('#inactive').html("<%= escape_javascript render :partial => 'calls/unassigned_calls', :locals => { :unassigned_calls => #unassigned, :region => #region } %>");
_assigned_calls.html.erb
<%= form_tag calls_path, :method => 'get' do %>
<%= select_tag "region[area]", options_from_collection_for_select(Region.order(:area), :id, :area, selected: region.try(:[], :area)), prompt: "Choose Region" %>
<%= submit_tag "Select", :name => nil, :class => 'btn' %>
<% end %>
Also, I think that better practice in your index.html.erb script tag
is to do it like this:
<script>
$(document).ready(function() {
setInterval(function () {
$.ajax({
url: 'calls_path',
type: "GET",
data: { "region": '<%= #region.html_safe %>' }
});
}, 5000);
});
</script>
Please test this out if you're interested and get back to me :)

link_to no route matches only after AJAX create of a post

Basically every time I create a post with AJAX, it won't render the new post because of this line:
<%= link_to "promote", vote_scribble_path(:scribble_id => scribble.id, :vote => true), remote: true, method: :post%>
THE LINK ABOVE ACTUALLY WORKS, it just prevents ajax render of newly created post.
here is the error that i get when trying to create new post with AJAX, it does actually create the post and it would render new post without the line above. After refresh of a page the new post with a working link appear.
Rendered scribbles/_scribbles.html.erb (18.9ms)
Rendered scribbles/create.js.erb (19.7ms)
Completed 500 Internal Server Error in 48ms
ActionController::RoutingError - No route matches {:action=>"vote", :controller=>"scribbles", :scribble_id=>155, :vote=>true}:
Here is the full code in action:
create.js.erb updates posts list after create
/*Replace the html of the div post_lists with the updated new one*/
$("#posts_list").html("<%= escape_javascript( render(:partial => "scribbles/scribbles") ) %>");
feedlist.html does render all of the posts
<div id="posts_list">
<%=render :partial => 'scribbles/scribbles', :locals => {:scribbles => #scribbles}%>
</div>
scribbles/_scribbles.html that link_to single line prevents ajax render. but it works.
<% #scribbles.each do |scribble| %>
<%= link_to "promote", vote_scribble_path(:scribble_id => scribble.id, :vote => true), remote: true, method: :post%>
<%end%>
even something like this gives me an error
<%= link_to "promote", vote_scribble_path()%>
vote_scribble_path(:scribble_id => scribble.id, :vote => true), remote: true, method: :post, :put,:get %> tried them all still same error
THE LINK WORKS IT JUST DOESN'T RENDER after AJAX CREATE, after page refresh everything is fine. any ideas why ?
resources :scribbles do
member do
post 'vote'
end
end
scribble_controller.rb
def vote
#scribble = Scribble.find(params[:scribble_id])
#vote = params[:vote]
if #vote == "true"
#v = :up
current_user.vote(#scribble, :direction => #v)
else
current_user.unvote_for(#scribble)
end
respond_to do |format|
format.js{}
end
end
You should be passing id instead of scribble_id in your link.
<%= link_to "promote", vote_scribble_path(:id => scribble.id, :vote => true), remote: true, method: :post%>
because as per your defined routes, the generated route for vote action would be:
vote_scribble POST /scribbles/:id/vote(.:format) scribbles#vote
which you can check by running rake routes.
As you can see vote_scribble_path is expecting an id placeholder and not a scribble_id which is why you receive the error as Rails cannot find a matching route in your application for scribbles#vote action with placeholder :scribble_id.

link_to doesnt replace div's content

the relevant controller code:
def show_host
queue = TestQueue.find(params[:id])
#test_queues = TestQueue.where(:host => queue.host)
respond_to do |format|
format.html { render action: "show_host", :layout => nil}
format.json { render json: #test_queue }
end
end
view:
<iframe name="host_queues", scrolling="yes" width="82%" height="700px", align="right", frameborder="0", rel="stylesheet"></iframe>
<%= link_to host, { :controller => "test_queues", :action => "show_host", :id => id}, {:target => "host_queues"} %>
now the thing is, it works with replace the content of the iframe, but when i try to replace content in a div with class="host_queues", it doesnt work... works only with iframe ..
can any1 out a finger on the reason ? 10x ..
target only applies to frames and windows. You have to use Javascript to replace the contents of a div.
use remote: true option in link_to and than write javascript
OR
use form_tag with remote: true, in update option, give div id which you want to replace
you can chek below link
http://guides.rubyonrails.org/working_with_javascript_in_rails.html

Categories