Rails data-remote attribute not always requesting a JS response - javascript

I have a form_for with remote: :true, but the problem is that it seems to only be submitted remotely about half of the time. Sometimes I will get a ActionController::UnknownFormat (ActionController::UnknownFormat) error from the server, which is configured to only respond to format.js, and most of the time the form will work perfectly.
Is there some way I can call $.rails to make sure that the data-remote binding is taking effect? I have turbolinks turned off. Here is the code for the form:
= form_for [:admin, #seating_chart], remote: 'true', authenticity_token: true, multipart: true do |f|
%br
.form-group.text-center
= f.label :name
= f.text_field :name, class: 'form-control'
.form-group.text-center
= f.label :venue_id
= f.collection_select :venue_id, Venue.all, :id, :name
.form-group.text-center
= f.label :chart_image
= f.file_field :chart_image, id: :seating_chart_file
.actions.text-center
= f.submit 'Save', class: 'btn btn-primary'
\|
= link_to 'Back', :back, class: 'btn btn-primary'
EDIT: upon further investigation it seems to only happen when I upload an image - if I don't upload the image then the error doesn't occur.

Since you are trying to upload file with ajax request it can't be achieved directly.
The solution for this case is remotipart
Remotipart
And this is a demo of it
Demo

Related

rails button_tag vs. button_to - class & id

I am trying to build a button with an id and a class with rails. A javascript event fires when the button get clicked. I tried different things none of them ticks all the boxes.
<%= button_tag "Launch the js event", id: "button-feedback-by-bullet" %>
This works but there is no class
<%= button_tag "Launch the js event", id: "button-feedback-by-bullet", class: "btn-primary" %>
I get an error saying there are too many arguments
<%= button_to "Launch the js event", id: "button-feedback-by-bullet", class: "btn-primary" %>
I get the right class but the button pass a post method and the js event does not get fired
Could you please help me find the right syntax and understand nuances between button_tag and button_to? Thanks.
button_tag(content_or_options = nil, options = nil, &block) public
You should do
<%= button_tag "Launch the js event", {id: "button-feedback-by-bullet", class: "btn-primary"} %>
or with button_to
button_to(name = nil, options = nil, html_options = nil, &block)
<%= button_to "Launch the js event", {}, {id: "button-feedback-by-bullet", class: "btn-primary"} %>
Also, button_tag or button_to triggers a submit by default, perhaps you should use link_to instead

Javascript is not executed

i cant figure out, why my javascript is not executed (and its really not executed).
/app/assets/javascripts/application.js:
//= require jquery
//= require bootstrap-sprockets
//= require turbolinks
//= require jquery_ujs
//= require_tree .
/app/controllers/project_controller.rb:
def upload
#projects = Project.all.order(updated_at: :desc)
#project = Project.find(params[:id])
respond_to do |format|
format.html
format.js {render layout: false}
end
end
/app/views/projects/show.html.erb:
<%= link_to project_upload_path, :project => #project.id, class: "btn btn-default" do %>
Upload
<%= glyph("plus") %>
<% end %>
/app/views/projects/upload.html.erb:
<div class="row">
<div class="col-xs-12">
<h2>Upload File to <%= #project.name %> project</h1>
</div>
<br>
<div class="col-xs-12">
<%= render :partial => "uploadform", :action => "savefile" %>
</div>
</div>
/app/views/projects/_uploadform.html.erb:
<%= form_for :upload, url: {action: "savefile"}, :multipart => true do |f| %>
<%= f.hidden_field(:project_id, :value => params[:id]) %>
<%= f.file_field :file, input_html: { hidden: true }, label: 'Upload Attachment' %>
<input id="file-display" class="input-large uneditable-input" type="text">
<%= f.submit "Save File", :class => "btn btn-default btn-file", :id => "upload-btn" %>
<% end %>
/app/views/projects/upload.js.erb:
$(document).on('ajax:success', function() {
alert("Test");
});
I tried everything. I added and removed "{render layout: false}" in my controller. I tried "page:change" and "turbolinks:load" in my upload.js.erb (instead of "ajax:success"). I tried all of the Java-Ready functions in "_uploadform.js.erb" (instead of "upload.js.erb"). I tried "remote: true" in link_to (show.html.erb) - but then it only executes js.erb (just the alert came up). I also updated Rails from 4.2.1 to 4.2.7.1 and tried "//= require jquery.turbolinks" in application.js (with all the document ready functions above).
As you can see in my log, it seems that it doesnt respond with the Javascript:
Started GET "/projects/upload/20" for 127.0.0.1 at 2016-10-05 14:05:48 +0200
Processing by ProjectsController#upload as HTML
Parameters: {"id"=>"20"}
Project Load (0.0ms) SELECT "projects".* FROM "projects" WHERE "projects"."id" = ? LIMIT 1 [["id", 20]]
Rendered projects/_uploadform.html.erb (0.0ms)
Rendered projects/upload.html.erb within layouts/application (2.4ms)
Completed 200 OK in 327ms (Views: 324.8ms | ActiveRecord: 0.0ms)
Please help me. I dont understand why this is not working in any way.
You need to tell rails to execute the post of the form via JavaScript. In the log you can see the PagesController is rendering HTML and not JS
Processing by ProjectsController#upload as HTML
Try adding :remote => true to your form_for helper
<%= form_for :upload, url: {action: "savefile"}, :multipart => true, :remote => true do |f| %>
<%= f.hidden_field(:project_id, :value => params[:id]) %>
<%= f.file_field :file, input_html: { hidden: true }, label: 'Upload Attachment' %>
<input id="file-display" class="input-large uneditable-input" type="text">
<%= f.submit "Save File", :class => "btn btn-default btn-file", :id => "upload-btn" %>
<% end %>
See the rails guides http://guides.rubyonrails.org/working_with_javascript_in_rails.html#form-for for more information.
It appears that you are attempting to upload files with an AJAX request, requiring the :multipart => true and :remote => true for your form definition.
File uploads can't be done using remote, however this issue is easily resolved by making use of Remotipart gem - it enables AJAX file uploads without any further changes to your code.
Add gem 'remotipart' to your Gemfile
Add //= require jquery.remotipart to application.js (after jquery_ujs)
Use remote: true and multipart: true in your form declaration
You should now be able to asynchronously upload files.
For further information check out https://github.com/JangoSteve/remotipart

Rails reCAPTCHA with callback

I am trying to integrate a recaptcha into my website and I wanted to add some client side validation.
I chose to use a gem to include the recaptcha tags, but I wanted to trigger a function once the recaptcha is checked.
Looked through some google sites and found that a data-callback attribute with its value set to function name is all I need.
I used recaptcha_tags helper from the gem to set it up and then a jquery method to add this data-callback attribute as I have not seed an option to do this inside the gem.
$('.g-recaptcha').attr("data-callback", "myFunctionName");
After clicking the recaptcha the function is not called. Why?
I asume you have a form like this
app/views/contacts/contact.html.erb
<%= form_for #contact do |f| %>
<%= f.text_field :nombre, :placeholder => I18n.t("contacto_formulario_nombre"),:required => true %>
<%= f.text_field :apellido :placeholder => I18n.t("contacto_formulario_apellidos"), :required => true %>
<%= f.text_field :email, :placeholder => I18n.t("contacto_formulario_email"), :required => true %>
/** (....other tags ....) **/
<%= recaptcha_tags :display => 'clean' %>
<%= f.button I18n.t("contacto_formulario_continuar"), type: "submit" %>
<% end %>
app/assets/javascripts/contact.js
$(function() {
$('.g-recaptcha').attr("data-callback", "recaptcha");
})
function recaptcha()
{
console.log("captcha pulsado!");
/** the actions you want, i.e. activate submit button **/
}
The magic ocurrs in the attribute "data-callback"
Hope it helps.
Marino

Preview image before upload with Carrierwave

I have a form where user can create new pictures. I've successfully done it with Carrierwave. I was wondering is it possible to preview selected image in browser before upload? I've found some try outs with javascript but didn't work for me.
This is the code for image upload with CARRIERWAVE:
<%= form_for #photo, :html => {:multipart => true} do |f| %>
<%= f.file_field :image %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="actions">
<%= f.submit "Save Photo" %>
</div>
<% end %>
My goal is to have one small thumbnail of image so user can see it before upload. I am guessing I can't use Rails here because it could be only for server side...
Any ideas? :)
If you are using bootstrap 3 there is an awesome extension for it here
http://jasny.github.io/bootstrap/javascript/#fileinput
I've found a lot of success in using Transloadit: https://transloadit.com/ and handing that off to Carrierwave on the success call. There is also a transloadit gem that makes things even easier: https://github.com/transloadit/rails-sdk. Using this method will give you a preview, modal, loading bar, and a bunch of other options you can turn on or off for a great user experience. It has the same options for resizing or cropping that carrierwave does, or you can hand it off to carrierwave to do it for you. Your jquery callback to your controller might look something like:
updateAttachment: function(fileName, attachmentType) {
var self = this;
$.ajax({
type: "PUT",
url: <your update url>,
data: {
attachment: {
file: fileName
}
},
success: function() {
location = self.windowLocation();
},
error: function() {
self.showError("Error uploading file.");
location = self.windowLocation();
}
});
}

Rails 4: form remote custom ajax request

I have a form where users can paste an URL for an image. And when the user submits the form I want to make an ajax GET request first which downloads the image client-side and checks it before proceeding for security purposes.
My problem ist that the remote form already does an ajax request and I can only access it with those before and complete bindings. But actually I need to chain them. When the image check is done, proceed with the POST ajax request from the form.
How can I do this?
(Sry, I'm using Slim)
= form_for #post, html: { class: "form-horizontal", role: "form" }, remote: true do |f|
.form-group
= f.label :author, "Name", class: "col-xs-1 control-label"
.col-xs-11
= f.text_field :author, class: "form-control", placeholder: "Name"
.form-group
= f.label :title, "Titel", class: "col-xs-1 control-label"
.col-xs-11
= f.text_field :title, class: "form-control", placeholder: "Titel"
.form-group
= f.label :text, "URL", class: "col-xs-1 control-label"
.col-xs-11
= f.url_field :text, class: "form-control", placeholder: "http://"
.form-group
.col-xs-offset-1.col-xs-11
= f.button :submit, class: "btn btn-default"
You could try listening on the ajax:before or ajax:beforeSend events that the UJS adapter for rails provides.
https://github.com/rails/jquery-ujs/wiki/ajax
According to the documentation, if you 'stop' those events using return false, the remote form request should never go through. So you can, via ajax, download the image in one of those events before the form is submitted and do your check there.

Categories