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();
}
});
}
Related
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/
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
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
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
I have a page that renders multiple forms. Currently, when the user submits any one of these forms, it updates (via ajax) a div on the same page with the content from the form that was just submitted.
I also want to remove() the form element that was just submitted after the ajax post request is completed. However, I need to be able to access that specific form ID within the js.erb file to do so.
Since my page has x number of forms rendered dynamically, I cannot simply access an instance variable in my js.erb.
Page:
<% for peer_review in #peer_reviews %>
<%= render :partial => 'form', :locals => { :peer_review => peer_review } %>
<% end %>
<div id="completed_peer_reviews">
<%= render 'completed_peer_reviews' %>
</div>
The #peer_reviews instance variable contains an array of new PeerReview objects already containing some data.
Form:
<div id="peer_review_form_<%= peer_review.reviewee_id %>">
<%= form_for peer_review, :html => { :method => "post" }, :remote => true do |f| %>
<%= f.error_messages %>
<p>
Peer Review for: <%= User.find(peer_review.reviewee_id).name %><br />
</p>
<p>
<%= f.label :rating %>:
<%= f.select :rating, [1, 2, 3, 4, 5], { :include_blank => 'None' } %>
</p>
<p>
<%= f.label :review %><br />
<%= f.text_area :review %>
</p>
<%= f.hidden_field :user_id, :value => peer_review.user_id %>
<%= f.hidden_field :reviewee_id, :value => peer_review.reviewee_id %>
<%= f.hidden_field :review_period_id, :value => peer_review.review_period_id %>
<p><%= f.submit "Submit" %></p>
<% end %>
</div>
js.erb:
$("#completed_peer_reviews").html("<%= escape_javascript(render('completed_peer_reviews')) %>");
I was hoping to just add another line to the js.erb file that removes the form element that just triggered the execution of the js.erb file like so:
$("#peer_review_form_<%= peer_review.reviewee_id %>").remove();
How should I actually be referencing peer_review.reviewee_id here? Or should I be taking a completely different approach?
This is one of the classic issues of RJS templates.
Quick answer:
If you simply want to solve the problem, you could pass along some temporary id to identify the form. e.g:
# in the index
<% #peer_reviews.each.with_index do |peer_review, i| %>
<%= render :partial => 'form',
:locals => { :peer_review => peer_review, :i => i } %>
<% end %>
# then in the form (note, you don't need to specify POST in a form_for)
<div id="peer_review_form_<%= i %>">
<%= form_for peer_review, :remote => true do |f| %>
<%= hidden_field_tag 'temp_id', i %>
# finally in the create js.erb
$("#peer_review_form_<%= params[:temp_id] %>").remove();
Longer Answer:
That being said, while RJS templates were "the Rails way" for a long time, they've since fallen out of favor.
The more modern method is typically client side JS templates with a JSON API, rather than running server generated JS templates (RJS). This has a lot of advantages, one being that the DOM binding issue you're having right now no longer exists.
This is an example of how you might do this with pure jQuery, but there are many templating options out there.
<script id="peer_review_tmpl" type="text/x-jquery-tmpl">
<div class="completed_peer_review">
<p>${review}</p>
...
</div>
</script>
Then you'd create a handler and bind it to a successful ajax response. This would require that your peer_reviews#create action responded to JSON:
$('form.new_peer_review').bind("ajax:success", function(data) {
// remove the form which triggered the creation
$(this).remove();
// then render the data into a template, and append it to the list
$("#peer_review_tmpl").tmpl(data).appendTo("#completed_peer_reviews");
});