Rails - How to make use of Active Storage JavaScript events - ruby-on-rails

I am working with Active Storage of RubyonRails, it seems that when a form is submitted certain JavaScript events are executed (at least this is what my understanding is) and I am trying to listen to these events.
My form is pretty simple just an input field and image field
<%= form_with(model: to_do, local: true, id: 'image_form') do |form| %>
<div class="field">
<%= form.label :title %>
<%= form.text_field :title, id: :to_do_title %>
</div>
<div class="field">
<%= form.label :image %>
<%= form.file_field :image, direct_upload: true %><br>
</div>
<div class="actions">
<%= form.submit id: 'submit_button' %>
</div>
<% end %>
Inside application.js file I added the following code to test what happens but unfortunately none of my tries work
addEventListener("direct-upload:initialize", doSomething, false);
function doSomething(e) {
alert("Event is called: " + e.type);
}
document.getElementById("image_form").addEventListener("direct-upload:initialize", function() {
console.log('direct-uploads:initialize')
});
document.getElementById("image_form").addEventListener("direct-uploads:end", function() {
console.log('direct-uploads:start')
});
When I submit the form although the data gets saved in database but my event listener does not listen to the event as i do not get any alert.
So my question is
How to listen to these Active Storage javascript events when a form is submitted?
Any help will be really appreciated.

It's likely that the form submission is happening too quickly, and therefore you can't see any of the event listener's output.
Start with adding this to your view with your form:
<%= form_with(model: to_do, local: true, id: 'image_form') do |form| %>
... form stuff ...
<% end %>
<script type="text/javascript">
console.log(document.querySelector('#image_form')); // Log the form, for debugging
document.querySelector('#image_form').addEventListener('direct-uploads:start', function() {
console.log('Event was called');
});
</script>
Additionally, you may want to preserve your web browser's console log prior to submitting the form, so you'd see the log message.

You can listen to events on the input field itself.
So in your case it will be
"#{model_name}_#{attachment_name}" which is to_do_image
document.getElementById("to_do_image").addEventListener("direct-upload:initialize",
function() {
console.log('direct-uploads:initialize')
});
document.getElementById("image_form").addEventListener("direct-uploads:end", function() {
console.log('direct-uploads:start')
});

Related

Rails 4.2: repopulating a dynamically populated thing after form validation error

I have a Rails 4.2 app. On my "New document" form, I have a select and a div containing a collection_check_boxes. When the user changes the value of the select, I use AJAX to repopulate the div containing the checkboxes so that the available checkboxes change depending on what item is selected in the select menu. The AJAX is working fine.
Here is the Javascript that detects when the select changes:
$(function() {
$(document).on('change', '#document_project_id', function(event) {
$.ajax('/populate_document_reviewer_list', {
type: 'GET',
dataType: 'script',
data: {
project_id: $("#document_project_id option:selected").val(),
}
});
});
});
My problem is that if something in the form fails validation, the form with errors is displayed. In this re-displayed form, the user's selection for the select is pre-populated, but the div containing the checkboxes displays the default choices because the onchange on the select did not fire so my AJAX to show the correct checkboxes is not called.
My question is, how can I display the correct checkboxes after a form validation error?
Solved it!
In my form, I added a conditional to check whether there were any errors. If there are errors, I populate the checkbox div manually based on the selected item in the select. If there are no errors, I display the default text.
<% if #doc.errors.any? %>
<% if #doc.project.is_secret? %>
<%= f.collection_check_boxes(:reviewer_ids, #doc.project.disclosed_users.order(:first_name, :last_name), :id, :name_with_job_title) do |b| %>
<%= b.check_box %> <%= b.label %><br>
<% end %>
<% else %>
<%= f.collection_check_boxes(:reviewer_ids, User.order(:first_name, :last_name), :id, :name_with_job_title) do |b| %>
<%= b.check_box %> <%= b.label %><br>
<% end %>
<% end %>
<% else %>
Select a project to see reviewers.
<% end %>

how to trigger onClick event on form_for textarea element

I'm using ruby on rails. I have a form created using form_for with a textarea. When the text area is clicked, I would like the height of the textarea to grow bigger. Coming from an asp.net mvc background, I would think to add an onClick event to the text area and then use jquery to add height px to the text area. I'm struggling on how to do this using rails:
<%= form_for(#person) do |f| %>
<%= f.label :name %>
<%= f.text_field :title, class: 'form-control' %>
<br/>
<div class="text">
<%= f.text_area :notes, placeholder: "add notes here...", id: "tester"%>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
I've managed to add an id of 'tester' to the text_area. I then placed this code in the application.js file:
$(document).ready -> {
$('#tester').bind('click', function() {
$('#tester').style.height = "200px";
});
}
I got this idea from the rails documentation here: http://guides.rubyonrails.org/working_with_javascript_in_rails.html
However this does not seem to be triggering the click event at all. How can this be accomplished in rails? Note: I am not familiar with coffee script and would prefer to use vanilla js.
Your element does not actually have an id "tester". Rails creates another id for it based on the object you're working on. Try to change $('#tester') in your javascript to $('.text textarea') and I think it will work.
I've discovered the answer. My code actually simply had an error in syntax. Here is the correct syntax for javascript code:
$( document ).ready(function() {
$('#tester').bind('click', function() {
$('#tester').attr("rows", "15");
});
});
The code I had originally for form_for was correct
Bind tester() function with onclick of textarea. When a user clicks on textarea the tester() will be triggered.
<%= f.text_area :notes, placeholder: 'add notes here...', onclick: 'tester()'%>
$( document ).ready(function() {
function tester() {
$(this).css('height', '200px');
});
}

Rails: if certiain value in form is selected, then populate another text_field

There is probably a simple solution for this, however, I couldn't find it.
I have a simple form where I have state select box & site text_field:
_form.html.erb
<div class="field">
<%= f.label :state, 'State' %><br>
<%= f.select :state, [['NSW'], ['VIC'], ['SA'], ['WA'], ['QLD']] %>
</div>
<div class="form-group">
<%= f.label :site, 'Site'%><br>
<%= f.text_field :site %>
</div>
I would really like to be able to select "VIC" (a state in Australia) and then due to the fact that "VIC" was selected, the :site text_field is automatically populated with another value such as a site name.
For example: "VIC" state is selected -> "Melbourne" site is populated in the text_field on the form (in :site)
I have played around a bit with some example javascript that I have found on the web which seems to update some text on the screen when a certain value is chosen in a select box, however, I cannot seem to form an "if" argument that states: if "VIC" selected, then populate text_field of :site with "Melbourne".
Thanks in advance.
code for javascript that changes to the value selected:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<div id="text_to_be_changed"><%= #day_of_week %></div>
<%= select_tag :days, options_for_select(["Monday", "Tuesday"]), :id => "select_days" %>
<script>
$(document).ready(function(){
$('#select_days').change(function() {
$('#text_to_be_changed').html($(this).val());
});
});
</script>
You can try this:
<script>
$(document).ready(function(){
$('#select_days').change(function() {
$('#text_to_be_changed').html($(this).val());
});
// adding pre-populate data
$("#configfile_state").change(function(){
var selected = $(this).val();
if(selected == "VIC") {
$("#configfile_site").val("Melbourne");
}
});
});
</script>
I hope this help you.
You will need the javascript to "know" the relationship between "VIC" and "Melbourne", or more generally between states and their capital cities. This can be stored in a variety of ways, eg as an array or map in your js code. eg
html:
<div class="field">
<%= f.label :state, 'State' %><br>
<%= f.select :state, [['NSW'], ['VIC'], ['SA'], ['WA'], ['QLD']], :id => "state-select" %>
</div>
<div class="form-group">
<%= f.label :site, 'Site'%><br>
<%= f.text_field :site, :id => "city-select" %>
</div>
js:
$(document).ready(function(){
var stateDefaultCities = {
"VIC": "Melbourne",
"NSW": "Sydney",
"WA": "Perth"
//etc
}
$('#state-select').change(function() {
$('#city-select').val(stateDefaultCities[$(this).val]);
});
});
EDIT: this solution is a bit fragile since the states are repeated in the markup and html: eg if you were to add an option to the select you'd need to add a corresponding line to the stateDefaultCities object. But it's just an example.

Submit a form after an event. Rails

Here is the part of code I am working on.
<td class= "block" id=<%= dom_id(Block.find(block.id)) %> colspan=2>
<%= form_for block do |f| %>
<%= f.text_area :content, :size => "5x4" %>
<%= f.hidden_field :id_case %>
<%= f.hidden_field :canvas_id %>
<%= f.submit "Submit", class: "save" %>
<% end %>
</td>
I would like to add another form under this one, still in the "td". And I would like this one to be submitted when I drag a special element in the (which is droppable)
I figured out that forms can have the data-remote attribut, but I didn't really get how we have to use it. Is this attribute made for execute javascript after we've submitted the form or is it a helper that submits the form after a special element ?
If this is the second case, it really fits with my idea but I really didn't understand how to use it.
Thanks for your help
I am not sure exactly what you want to know here, but a form with data-remote="true" means that it will be submitted by Ajax rather than a 'normal' submit. You can add remote: true to your form like this:
<%= form_for(#post, remote: true) do |f| %>
...
<% end %>
The resulting form will have a data-remote="true".
To submit a form by Ajax after you have dropped your element you can do the following using jQuery:
$("#your-droppable-element").droppable({
drop: function( event, ui ) {
$('#your-form').submit();
}
});
I hope that helped :)

Jquery ajax spinner relative to multiple form fields

I am trying to load two spinners on two fields, in the same (rails) form, that both have a keyup remote call.
Using Jquery, I have the following code:
<div class="form_element">
<%= f.label :email, :class=>"field_hint", :title=>"Email" %>
<%= f.text_field :email %>
<div class="myloader" style="display:none;">
<p>
validating...
</p>
</div>
</div>
<div class="form_element">
<%= f.label :username, :class=>"field_hint", :title=>"Username" %>
<%= f.text_field :username %>
<div class="myloader" style="display:none;">
<p>
validating...
</p>
</div>
</div>
Both of these fields have a keyup that does a remote call:
$('.form_element').ajaxStart(function() {
$(this).children('.myloader').show();
});
$('.form_element').ajaxStop(function() {
$(this).children('.myloader').delay(1000).fadeOut('fast');
});
At the moment when an the ajax happens both spinners appear when I only want the spinner who is a sibling of the field, I am trying to work out how to make each spinner div relevant to its field.
I am new to Ajax so any advice on maybe doing the ajaxStart/Stop differently are more than welcome, maybe a way to only have one spinner which moves next to the field instead of having two would be helpful.
I encourage you to use this jQuery plugin for your task: http://plugins.jquery.com/project/nimbleLoader
It will allow you to create loading bar for any element in your web page. Here you can see example: http://www.salesclic.com/jquery.nimble.loader/demo/

Resources