jQuery Event handlers not working properly - javascript

The jQuery Event handlers work well on a fresh page but after I change page using the links present in layout, they stop working. I am unable to figure out what's wrong with my code.
I have the following files in my rails app:
layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>LogManager</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<h1>Analytics</h1>
<%= link_to "All",analytics_all_path %> | <%= link_to "Aggregation",analytics_aggregation_path %>
</body>
</html>
analytics.js
$(function() {
$("#js-analyze-aggregation").click(function(){
alert("Hehe");
});
});
$(function() {
$("#js-analyze").click(function(){
alert("Hehe");
$.ajax({
type: "GET",
url: "/api/logs",
success: function(data) {
Analytics.doAnalysis(data);
}
});
});
});
analytics/all.html.erb
<button type="button" id="js-analyze">Analyse</button>
analytics/aggregation.html.erb
<textarea id="body_data" cols="60" rows="10"></textarea>
<br>
<button type="button" id="js-analyze-aggregation">Analyse Filtered Data</button>

Try changing ur JS to
$(function() {
$("#js-analyze-aggregation").on('click', function(){
alert("Hehe");
});
});
$(function() {
$("#js-analyze").on('click', function(){
alert("Hehe");
$.ajax({
type: "GET",
url: "/api/logs",
success: function(data) {
Analytics.doAnalysis(data);
}
});
});
});
When you use turbolinks, new elements come inside DOM and event handler is not bind to them. Check here In jQuery, how to attach events to dynamic html elements?

Related

Rails js.erb not rendering partial file but get response file rendered

I have the following partial files
_report.html.erb
<h5>REPORT</h5>
<hr/>
<%= link_to "Extract REPORT", "#", :class => 'btn btn-primary', id: 'load_panel' %>
<br/>
<br/>
<div class="row">
<% rand = Time.now.to_i - Random.new.rand(1..Time.now.to_i) %>
<div class="col-md-12">
<input type="hidden" id="randValue" value="<%= rand %>" data-validate="false" data-hidden="true"/>
<div>
<b>File Name</b>
<hr/>
</div>
<div id="application-attachments-<%= rand %>" class="col-xs-12">
<%= render partial: 'report_attachment', locals: {application_attachments: f.object.application_attachments} %>
</div>
</div>
</div>
_report_attachment.html.erb
<% application_attachments.each do |attachment| %>
<div class="fields">
<%= render "report_attachment_fields", rep_attachment: attachment, instalment: true, type: 'application_assignment' %>
</div>
<% end %>
_report_attachment_fields.html.erb
<div class="row attachment_display">
<% if rep_attachment.attachment? && rep_attachment.attachment.model.share_file %>
<% if #action == "show" && #account_type %>
<div class="col-md-6 ellipis">
<%= link_to File.basename(rep_attachment.attachment.path), rep.attachment.url, target: "_blank", id: 'view_file', :data => { application_attachment_id: rep_attachment.id } %>
<%= rep_attachment.active %>
</div>
<% end %>
<% end %>
</div>
Upon initial load, it loads all 3 files accordingly. But Upon clicking Extract CTOS, it makes a javascript request
application.js
$('body').on('click', '#load_panel', function(event) {
object_selected = $(this)
$(this).attr('disabled', 'disabled');
$.ajax({
type: 'GET',
url: '/applications/generate_report?application_id='+$(this).attr('data-application-id')+'&rand_value='+$(this).attr('data-rand-value'),
dataType: 'json',
success: function(data) {
object_selected.removeAttr('disabled');
}
})
})
On calling the GET request, it will call this method
def generate_report
#rand_value = params[:rand_value]
#rep_application_attachment = #application.rep_attachment
respond_to do |format|
format.js
end
end
Which should call this js.erb file
generate_report.js.erb
$("#application-attachments-#{#rand_value}").html("<%= escape_javascript(render 'report_attachment', application_attachments: #rep_application_attachment) %>");
The problem now is that i dont get an error and it says generate_report.js.erb has been rendered but it doesnt render anything. What am i missing?
solved it. It had to do with my ajax call.
$.ajax({
type: 'GET',
url: '/applications/generate_report?application_id='+$(this).attr('data-application-id')+'&rand_value='+$(this).attr('data-rand-value'),
dataType: 'json',
success: function(data) {
object_selected.removeAttr('disabled');
}
})
should be this instead. by not including datatype ='script' and correct format, even though my js.erb got called, it wasn't executed.
$.ajax({
type: 'GET',
url: '/applications/generate_report?application_id='+$(this).attr('data-application-id')+'&rand_value='+$(this).attr('data-rand-value'),
data: {
format: 'js'
},
dataType: 'script',
success: function(data) {
object_selected.removeAttr('disabled');
}
})
You need to specify 'partial' option to render template using render method.
Try this
generate_report.js.erb
$("#application-attachments-#{#rand_value}").html("<%= escape_javascript(render partial: 'report_attachment', application_attachments: #rep_application_attachment) %>");
your original code:
$("#application-attachments-#{#rand_value}").html("<%= escape_javascript(render 'report_attachment', application_attachments: #rep_application_attachment) %>");
Rendering partials
Partial rendering in a controller is most commonly used together with Ajax calls that only update one or a few elements on a page without reloading. Rendering of partials from the controller makes it possible to use the same partial template in both the full-page rendering (by calling it from within the template) and when sub-page updates happen (from the controller action responding to Ajax calls). By default, the current layout is not used.
For more information about render
https://apidock.com/rails/ActionController/Base/render
I think the problem is that you're trying to interpolate your ruby instance variable the wrong way (you're using Ruby's string interpolation syntax "#{}"), when you need to use ERB "<%= %>".
This should work:
$("#application-attachments-<%= #rand_value %>").html("<%= escape_javascript(render 'report_attachment', application_attachments: #rep_application_attachment) %>");

Ruby on Rails:Can not call ajax callback from form_tag

In my view (/app/view/media/index.html.erb) , i have an ajax function and a form_tags:
My AJAX function:
<script type="text/javascript" charset="utf-8">
$(document).ready(
function () {
$("#my_ajax").bind("ajax:success",
function (evt, data, status, xhr) {
console.log(data);
}
).bind("ajax:error", function (evt, data, status, xhr) {
console.log("doh!")
});
});
</script>
.
And my form_tags:
<%= form_tag '/delete_media', method: :delete do %>
<%= submit_tag 'Delete', class: 'btn btn-danger', disabled:#media_contents.empty? , :remote => true, :id => "my_ajax" %>
Our goal : when i get response from server after submit, my_ajax function will be run.
How to do it ??? I can not trigger "my_ajax" function ? I always get JSON response from server
EDIT:
My controller :
def delete_media
#medias=Media.where(id: params[:media_contents]).destroy_all
render json: #medias
end
You should not write js handle ajax like that.
Properly way to implement ajax in rails is:
In /app/view/media/index.html.erb:
form_tag ..., remote: true
In media Controller:
def destroy
# do your job
respond_to do |format|
format.js {}
end
end
In /app/view/media/destroy.js.erb:
// your js handle code
More information: http://guides.rubyonrails.org/working_with_javascript_in_rails.html
maybe try something like this:
<script>
$(document).ready(function(){
$("#my_ajax").on('ajax:success', function(e, data, status, xhr){
console.log(data);
}).on('ajax:error',function(e, xhr, status, error){
console.log('doh!')
});
});
</script>

How to make a file loading progress bar for the rails form?

I'm trying to make a form that has an title, email, content and file upload fields. When the user click submit the uploaded file is saved in the database and the link with the location and hashed name is send to admin. That all works but the files that users are gonna upload are big and I would like to have some loading bar. I know there are many similar questions on stackoverflow but I was not able to make it work.
First I set two routes:
get "message", to: "messages#index"
post "message_create", to: "messages#create"
Over the first I get the form:
<%= form_tag(message_create_path, :method=>'post', class: "section form", :multipart => true) do %>
<fieldset class="form__fieldset">
<div class="form__field">
<%= text_field_tag 'name', nil, class: 'input', placeholder: 'Name', id: 'name' %>
</div>
<div class="form__field">
<%= text_field_tag 'email', nil, class: 'input', placeholder: 'Email', id: 'email' %>
</div>
<div class="form__field">
<%= text_area_tag 'content', nil, class: 'input textarea', rows: '10', placeholder: 'content', id: 'content' %>
</div>
<div class="form__field">
<%= file_field_tag 'file', id: 'input_file' %>
</div>
<div class="progress">
<div class="bar"></div >
<div class="js-percent">0%</div >
</div>
</fieldset>
<fieldset class="form__fieldset">
<%= submit_tag 'send', :class => "btn btn--dark-ghost", :id => "submit" %>
</fieldset>
<%end%>
The form should then post to the second route.
To make the loading progress visible I try to use this:
$("#submit").click(function() {
var file_data = $("#input_file").get(0).files[0]
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
//Upload progress
xhr.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
$(".js-percent").text(String(percentComplete*100) + "%")
}
}, false);
return xhr;
},
url: "message_create",
type: "POST",
data: JSON.stringify(file_data),
contentType: "application/json",
dataType: "json"
});
});
When I try to submit the file the text 0% joust jumps to 100% but I see that the browser is still uploading.
I can't make it work because I don't know ajax so please help me fix this loading progress problem and I'd appreciated if you can recommend me some good tutorials for learning Ajax.
Thank you!

How to execute Javascript after Rails' remote form `disable_with` functionality has completed?

I am using disable_with, and cannot get the button text change to persist (because it is being overwritten by the disable_with functionality). As soon as I remove , data: { disable_with: '...' the buttons are updated as expected.
Is there a way to perform actions after the disable_with functionality has completed?
form:
<%= form_for #user, html: {id: 'follow-form'}, remote: true do |f| %>
<%= button_tag id: 'follow-btn', data: { disable_with: '...' } do %>
Follow
<% end %>
<% end %>
js:
$('#follow-form').on('ajax:success',function(data, status, xhr){
if (status.action == 'follow') {
$('#follow-btn').text('Unfollow');
} else {
$('#follow-btn').text('Follow');
}
}
Maybe without disable_with and:
$('#follow-form').on('ajax:send',function(data, status, xhr){
$('#follow-btn').text('Please wait...').attr({disabled: true});
});
And when AJAX request succeeds:
$('#follow-form').on('ajax:success',function(data, status, xhr){
if (status.action == 'follow') {
$('#follow-btn').text('Unfollow').attr({disabled: false});
} else {
$('#follow-btn').text('Follow').attr({disabled: false});
}
});

Passing JavaScript variable to ruby-on-rails controller

How can I pass a variable (id) from the JavaScript listener:
Gmaps.map.callback = function() {
...
...
google.maps.event.addListener(marker, 'click', function() {
var id = this.currentMarker;
alert(id);
});
}
}
To the instance variable (#foo) in ruby-on-rails controller
def create
#foo = ???
...
end
to correctly create a relationship in the view (form):
<%= form_for user.relationships.build(:followed_id => #foo.id) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<div class="actions"><%= f.submit "Follow" %></div>
<% end %>
Thanks!
If I am understanding correctly, a good way to do this is to use AJAX to submit the id to your action and use the action to render your form.
That would look something like this in your javascript:
jQuery.ajax({
data: 'id=' + id,
dataType: 'script',
type: 'post',
url: "/controller/action"
});
You'll need a route:
post 'controller/action/:id' => 'controller#action'
Then in your action you can grab that id and render your form something like this:
def action
#user = User.relationships.build(:followed_id => params[:id])
render :viewname, :layout => false
end
Then you can just build a form for #user in a partial or whatever
<%= form_for #user do |f| %>
You'll have to fill in the details there, but that should get you pretty close.

Categories