Rails AJAX / Spinner not working properly - javascript

My spinner show but only from the second search occurence on...
When I search for a stock the first time nothing appears. Here's my repo: https://github.com/Ardzii/finance-tracker and the heroku: https://finance-tracker-ardzii.herokuapp.com/
And, so that you don't have to look the repo:
Here's the view: _lookup.html.erb (partial)
<div id="stock-lookup">
<h3>Search for stocks</h3>
<%= form_tag search_stocks_path, remote: true, method: :get, id: 'stock-lookup-form', spinner: true do %>
<div class="form-group row no-padding text-center col-md-12">
<div class="col-md-10">
<%= text_field_tag :stock, params[:stock], placeholder: "Stock ticker symbol", autofocus: true, class: 'form-control search-box input-lg' %>
</div>
<div class="col-md-2">
<%= button_tag(type: :submit, class: "btn btn-lg btn-success") do %>
<i class="glyphicon glyphicon-search"></i> Look up a stock
<% end %>
</div>
</div>
<%= render 'common/spinner' %>
<div id='stock-lookup-results'></div>
<% end %>
</div>
The spinner partial: _spinner.html.erb
<div id="spinner" class="row col-md-12 text-center spinner" style="display: none;">
<i class="glyphicon glyphicon-refresh glyphicon-spin"></i> Processing...
</div>
My Javascript file: search.js.erb
var init_stock_lookup;
init_stock_lookup = function(){
$('#stock-lookup-form').on('ajax:before', function(event, data, status){
show_spinner();
});
$('#stock-lookup-form').on('ajax:complete', function(event, data, status){
hide_spinner();
});
$('#stock-lookup-form').on('ajax:success', function(event, data, status){
$('#stock-lookup-results').html("<%= j render 'stock', {stock: #stock} %>");
init_stock_lookup();
});
}
$(document).ready(function() {
init_stock_lookup();
})
The view it renders: _stock.html.erb
<div class="well results-block">
<% if stock.present? %>
<strong>Symbol:</strong> <%= stock.ticker %>
<strong>Name:</strong> <%= stock.name %>
<strong>Price:</strong> <%= stock.price %>
<% else %>
<i>Stock not found</i>
<% end %>
</div>
My application.js file:
var hide_spinner = function (){
$("#spinner").hide();
}
var show_spinner = function (){
$("#spinner").show();
}
I'm not sure the problem was stated really clearly, so I will restate it here:
The spinner works only after a first search. On the first lookup, I have no spinner being displayed...
Thanks in advance and as usual for your help!

Related

uncaught TypeError: ajaxForm is not a function in rails version 5?

I am trying to submit the modal form using ajaxForm and display the response in modal itself. But, I am getting uncaught type error (...).ajaxForm is not a function.
Basically I want to create a modal form for lesson creation form and have to submit , my app consists of both API controller and front end controller.
api!
param_group :lesson
description 'creates a lesson'
example "
{
'id': 12,
'title': 'MUDRAS',
'active_video_id': 3,
'description': 'Description of the lesson',
'points': null,
'is_public': '1',
'videos': [
{
'video': {
'id': 1,
'video': {
'url': '/uploads/video/video/1/250-authentication-from-scratch.mp4'
},
'title': null,
'storage_type': 'Lesson',
'storage_id': 12
}
},
]
}"
def create
#lesson = Lesson.new(lesson_params)
#lesson.creator = current_user
if #lesson.save
render json: {
success: true,
message: "Lesson created Successfully"
}
else
render json: { success: false, message: "Could not Create : #{#lesson.errors.full_messages.join(', ')}" }
end
end
def new
#lesson = Lesson.new
end
The above code is my API controller.The below codes are my Front end controller and lesson related forms.
def create
#lesson = Lesson.new(lesson_params)
if #lesson.save
render json: {
success: true,
message: "Lesson Created Successfully"
}
else
render json: {
success: false,
message: "Lesson Creation Failed"
}
end
end
I need to display the "New Lesson" button in Lesson Index page.
lessons/index.html.erb
<% unless current_user.student? %>
<div class="container-fluid">
<div class="col-md-3 col-sm-3 text-left">
<div id="newLesson" class="lesson-category btn-danger" lesson_url="<%= new_lesson_path %>">
<i class="fa fa-plus"></i> ADD LESSON
</div>
</div>
</div>
<div class="hidden" id="newLessonForm">
<% #lesson = Lesson.new ; #lesson.videos = [Video.new] %>
<%= render "lessons/form" %>
</div>
<% end %>
<%= render "shared/primary_modal" %>
<div class="container-fluid">
<div class="col-md-3 col-sm-3 text-left">
<h2 class="main-tab tab-active">LESSONS</h2>
</div>
<div class="col-md-9">
<div class="col-md-12 text-right">
<h2 class="main-tab tab-inactive"><a id="responsesLink" class="blacko" href="#"><%= "MY" if current_user.student? %> RESPONSES</a></h2>
</div>
</div>
<div class="col-md-12"><hr/></div>
<!-- Lessons of this course Go here -->
<div class="col-md-3">
<% #lessons.each do |lesson| %>
<div id="lesson_<%= lesson.id %>" class="pill video-view lesson-load" data-lesson-id="<%= lesson.id %>" data-src="<%= lesson.active_video_url %>"><%= lesson.title %></div>
<% end %>
<!-- <div class="pill pill-inactive">Something</div> -->
</div>
<!-- Lesson Content goes here -->
<div class="col-md-9">
<div class="row">
<div class="col-md-12">
<%= render "shared/video_player" %>
</div>
</div>
<div id="lessonContent">
</div>
</div>
</div>
<script>
$("#newLesson").click(function(){
var lesson_path = $(this).attr("lesson_url");
$.get(
lesson_path,
function(content){
$("#primaryModalContent").html(content);
$("#format").val('js');
$("#primaryModal").modal("show");
}
);
});
</script>
My lesson creation form is given as a partial.
<div class="col-md-12">
<%= simple_form_for #lesson, html: {class: "newLessonform"} do |f| %>
<%= f.input :title, label: "Lesson Title", required: false %>
<%= f.input :description, required: false, as: :text %>
<%= f.input :points, required: false, as: :integer %>
<%= f.input :is_public, label: 'Check to Make this lesson public', as: :boolean %>
<div class="col-md-12">
<% unless #lesson.new_record? or #lesson.active_video_url.blank? %>
<h4> Currently Linked Video </h4>
<video src="<%= #lesson.active_video_url %>" style="width: 400px;"></video>
<% end %>
<hr/>
</div>
<h4>Add <%= #lesson.videos.blank? ? "a" : "another" %> Video</h4>
<% #lesson.videos = [Video.new(title: "")] if #lesson.videos.blank? %>
<%= f.simple_fields_for :videos do |g| %>
<%= g.input :title, label: "Video title" %>
<%= g.input :video, as: :file, lebel: "Select Video" %>
<% end %>
<center><%= f.submit class: "lesson-category btn-danger" %></center>
<% end %>
</div>
<script type="text/javascript">
$(".newLessonform").ajaxForm(function(data) {
$("#primaryModalContent").html(data.message);
});
</script>
In the above script , I have given ajaxForm. The modal form for this is given below.
<div class="modal fade" id="primaryModal" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" , data-dismiss="modal">×</button>
<h1 class="modal-title" id="modalTitle"></h1>
</div>
<div class="row modal-body" id="primaryModalContent">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
The error in chrome console , was uncaught error:(...)$.ajaxForm is not a function.
I am stuck in this for about a week. Could any one give me a solution.
Thanks in advance.
The best way to use an AJAX form in rails is to use rails_ujs.
First you have to tell rails_ujs that you want an AJAX action on your form :
<%= simple_form_for #lesson, html: {class: "newLessonform"}, remote: true do |f| %>
Then add a new file in your views, this view will be rendered after a successfull create action initiated by an AJAX action : views/lessons/create.js.erb
Inside you can put you js code, this code will be executed on the same page as the AJAX form. This is just a view and you can use variables from the controller.
$("#primaryModalContent").html("<%= #message %>")
Finally, you need to update your controller to handle AJAX action :
def create
#lesson = Lesson.new(lesson_params)
if #lesson.save
#success = true
#message = "Lesson Created Successfully"
else
#success = false,
#message = "Lesson Creation Failed"
end
respond_to do |format|
format.js
end
end
Here you can find some documentation about Rails UJS :
http://guides.rubyonrails.org/working_with_javascript_in_rails.html#remote-elements
https://blog.codeship.com/unobtrusive-javascript-via-ajax-rails/

Rails 5 : AJAX variable undefined on ajax:error / ajax:success events

I have a form_with that calls a controller that responds in JSON. I would like to run javascript (handle errors, ...) during an event ajax:success or ajax:error.
I followed the Rails documentation. Unfortunately, the variables in my events are undefined. Only e are set.
Form:
<%= form_with url: contact_path, scope: 'message', id: 'new_message' do |f| %>
<div class="row">
<div class="input-field col s6">
<%= f.text_field :name, class: 'validate' %>
<%= f.label :name, 'Nom' %>
</div>
<div class="input-field col s6">
<%= f.email_field :email, class: 'validate' %>
<%= f.label :email, 'Email' %>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<%= f.telephone_field :phone, class: 'validate' %>
<%= f.label :phone, 'Téléphone' %>
</div>
<div class="input-field col s6">
<%= f.text_field :website, class: 'validate' %>
<%= f.label :website, 'Site Web' %>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<%= f.text_area :content, class: 'materialize-textarea validate' %>
<%= f.label :content, 'Message' %>
</div>
</div>
<div class="row">
<div class="col s6">
<%= recaptcha_tags %>
</div>
<div class="col s6">
<%= button_tag class: 'btn primary waves-effect waves-light right' do %>
Envoyer
<i class="material-icons right">send</i>
<% end %>
</div>
</div>
<% end %>
Controller:
def create
#message = Message.new(message_params)
respond_to do |format|
if verify_recaptcha(model: #message) && #message.valid?
MessageMailer.new_message(#message).deliver
format.json { render json: #message, status: :created }
else
format.json { render json: #message.errors, status: :unprocessable_entity }
end
end
end
CoffeeScript:
$(document).ready ->
$("#new_message").on("ajax:success", (e, data, status, xhr) ->
console.log(xhr);
).on "ajax:error", (e, xhr, status, error) ->
console.log(xhr);
Result:
undefined message.self-5eda06948d26dade035273a7f168828c2cb1852e26937c49f50da7ca2532ad72.js:4:14
Started POST "/contact" for 127.0.0.1 at 2017-06-13 17:19:17 +0200
Processing by MessagesController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"aBxh+eJedXw0WifdUXFAlgH0gWxNpiDQa2J3hdJayC/wBaccIxNSVK4pycYwu9XMb1s2/r9S8+FteRFoocdrZQ==", "messages"=>{"name"=>"", "email"=>"", "phone"=>"", "website"=>"", "content"=>""}, "g-recaptcha-response"=>"03AOPBWq9SEfWUxzdyMRMdd0p65vonbGjNjA_mhCA07vfoXyA6_nEVn220Ot5HU90_KpQv6ziii0VCoa1hZosUcsARL7DuJbFHA2kt_NBHvnURmPpKR0SMq0OfulzJokvobdu9t1z33Uby3oTAtTgEAEmxX6yDc_yuwmqHXAjh5SL0bhAyD6AF2wAN8me7fMKMULu_DS5KtLgwJjK8B2TmvGydn0neHDWcfSbDKP7WRP-RQQePc9hDcOCbUFoVrW2kfpg3p4OV-hWiV4q6-HBRZK3A1mcj5rJZd_zBe3v-yx6LHAXB2Bsb9Uc", "button"=>""}
Completed 422 Unprocessable Entity in 2701ms (Views: 0.5ms | ActiveRecord: 856.3ms)
If you are using the rails-ujs adapter, according to this Rails Edge Guide:
Signature of calls to UJS's event handlers has changed. Unlike the
version with jQuery, all custom events return only one parameter:
event. In this parameter, there is an additional attribute detail
which contains an array of extra parameters.
I'd suggest taking a look at your app/assets/javascripts/application.js and find out which ujs adapter you are currently using. //= require rails-ujs is the new default.
Take a look at the example provided in the guide. You can extract data, status, and xhr in the following manner.
document.body.addEventListener('ajax:success', function(event) {
var detail = event.detail;
var data = detail[0], status = detail[1], xhr = detail[2];
})
Another alternative is to to use jquery_ujs which was the default prior to Rails 5.1 and has a signature more like you were expecting.

Is jQuery .append breaking my Rails form and causing it not to fully render?

Running into a strange issue. I using jQuery's .append() to place a <div> containing a Rails form next to the paragraph tag a user selects in my Rails app.
First off, before adding the jQuery effect, I tested this by placing a the form on the page. It loaded, worked, and posted the user's text to my database correctly.
Second, I added this effect, and the <div> with the form does load, but weirdly, you cannot click into it. The text cursor will appear for a moment, disappear, and the user can not actually enter anything in the text_field.
Here's what I am running:
view.html.erb
<% #posts.each do |post| %>
<h2 id="title"><%= post.title %></h2>
<div id="paragraph"><%= markdown(post.content) %></div>
<% end %>
<div class="exampleToggle"> <!-- div that should append -->
<%= form_for :comments do |f| %>
<div class="form-group">
<div class="field">
<%= f.label :username %><br>
<%= f.text_field :username, class: "form-control" %>
</div>
</div>
<div class="form-group">
<div class="field">
<%= f.label :post %><br>
<%= f.text_area :post, class: "form-control" %>
</div>
</div>
<div class="actions">
<%= f.submit "Save", class: "btn btn-success-outline" %>
</div>
<% end %>
</div>
<script>
$(document).ready(function(){
var whatever = document.getElementsByClassName("exampleToggle");
$("p").click(function(){
$(this).append(whatever);
});
});
</script>
As I mentioned, the form does load and looks how it should after clicking on a paragraph element; however, the form will not accept text input.
Also, for clarity's sake, here is the CSS involved with the placing the <div> to the right of the clicked paragraph:
{
position: relative;
}
.exampleToggle {
position: absolute;
top: 0;
margin-left: 8%;
left: 100%;
width: 35%;
height: 100px;
}
Any idea why this is breaking the form/form helper?
EDIT 1: For clarity, the central issue here seems to be the Focus effect. To try and fix this, I updated the Javascript to allow for value entry when the .field class is activated, but it did not fix it. Here's what I tried.
<script>
$(document).ready(function(){
var whatever = document.getElementsByClassName("exampleToggle");
$("p").click(function(){
$(this).append(whatever);
});
$('.field').click(function () {
var val = $(this).val();
if (val == "") {
this.select();
}
});
});
</script>
You have given $("p"), but there is no p tag in your question.
Also you are looping the same id to different fields which is not correct, ID should be unique. Instead take the class instead of id.
You should take a class to the paragraphed_id field and should write the jquery functions based on the required classes.
Try this,
<% #posts.each do |post| %>
<h2 id="title"><%= post.title %></h2>
<div class="paragraph"><%= markdown(post.content) %></div>
<% end %>
<div class="exampleToggle"> <!-- div that should append -->
<%= form_for :comments do |f| %>
<div class="form-group">
<div class="field">
<%= f.label :username %><br>
<%= f.text_field :username, class: "form-control" %>
</div>
</div>
<div class="form-group">
<div class="field">
<%= f.label :post %><br>
<%= f.text_area :post, class: "form-control" %>
</div>
</div>
<div class="actions">
<%= f.submit "Save", class: "btn btn-success-outline" %>
</div>
<% end %>
</div>
<script>
$(document).ready(function(){
var whatever = document.getElementsByClassName("exampleToggle");
$(".paragraph").click(function(){
$(this).append(whatever);
});
});
</script>

Rails: Submit html table content in form to controller

I have some trouble with an rails formular.
I have a form to create "projects".
Project form
<%= bootstrap_form_for(#project) do |f| %>
...
<div class="container-fluid">
<%= f.static_control label:"Vordefinierte Aufgaben" do %>
<div class="actions form-group nopadding">
<div class="center-block">
<%=link_to "", data: {toggle:"modal", target:".newTask-modal"} , class: "btn btn-success center-block btn-sidebar-ok", id: "singlebutton" do%>
<i> <span class="glyphicon glyphicon-plus pull-left btn-sidebar-icon"></span>Neue Aufgabe hinzufügen </i>
<% end %>
</div>
</div>
<div class="task-table">
<%=render 'tasks/table'%>
</div>
<% end %>
</div>
...
<!-- task Modal to create a new task -->
<%=render 'tasks/newTaskModal' %>
<% end %>
<!-- Button -->
<div class="actions form-group">
<div class="center-block">
<%= button_tag( type: 'submit', class: "btn btn-success center-block btn-sidebar-ok", id: "singlebutton") do%>
<i> <span class="glyphicon glyphicon-ok pull-left"></span>Projekt anlegen </i>
<% end %>
</div>
</div>
Within this form a have a table which shows created tasks and a button to open an bootstrap modal. This modal contains a new form to create a task.
Task Form within modal
<%= bootstrap_form_tag() do |f| %>
<div class="col-sm-8">
<%= f.text_field :task_title, label: "Titel", placeholder: "Betreff", icon: "pencil",wrapper: { class: 'icon-addon addon-md'} %>
</div>
<div class="col-sm-4">
<%= f.number_field :task_in_min, label: "Arbeitszeit in Min", placeholder: "Bsp.: 25", icon: "time", wrapper: { class: 'icon-addon addon-md'}%>
</div>
<div class="col-sm-12">
<%= f.text_area :task_description, label: "Beschreibung*", placeholder: "Aufgabenbeschreibung", icon: "pencil", rows: 10, wrapper: { class: 'icon-addon addon-md'}%>
</div>
<%= button_tag( type: 'button', id:"taskSubmit", class: "btn btn-success center-block btn-sidebar-ok") do %>
<i > <span class="glyphicon glyphicon-ok pull-left btn-sidebar-icon"></span> Speichern </i>
<% end %>
<% end %>
If I click to "taskSubmit" a javascript put this task (title, description, min) into the table within the project form. JS create a new table row with the task content.
Javascript
//take data from task form and at a new task element to the task table in project form
$(function TaskSubmitFunction(){
$('#taskSubmit').click(function(){
var task_title = $('#task_title').val();
var task_description = $('#task_description').val();
var task_in_min = $('#task_in_min').val();
//Remove spaces from title
var id = task_title.replace(/ /g,'');
$('#taskTable tr:last').after('<tr id="task_'+id+'"> <td>'+task_title+'</td> <td>'+task_description+'</td><td>'+task_in_min+'</td><td> <span class="pull-right"><span data-toggle="tooltip" data-placement="right" data-original-title="Löschen"><button class="btn btn-sm btn-danger btn-colored delete-position" id="'+id+'"name="button" type="button" task="'+task_title+'"><i><span class="glyphicon glyphicon-remove"/></i></button></span></span></td></tr>');
$('#taskTable').after('<input type="hidden" id="1" name="1" value="'+task_title+'" />');
$('#task_title').val('');
$('#task_description').val('');
$('#task_in_min').val('');
//initialize task delete
$(function TaskDeleteFunction(){
$('#'+id).click(function(){
var task_title = $(this).attr('task');
if (confirm("Soll die Aufgabe wirklich gelöscht werden?")) {
$('#'+id).remove();
}
return false;
});
});
});
});
What I want to do now is to submit these table elements to the project controller to create the project and all necessary tasks activeRecords. Is this possible?
How can I do this? Maybe create a hidden field for every table element which will be submit to the project form? But every table element consists of three values... how can I do this?
Do you have any idea?
best regards
Why not just use three hidden fields (one for each value)? Straightforward and they will be easy to access in the params hash.

Using Ajax to replace a div with a partial in Rails

I'm following Ryan Bates' Railscast #136 and trying to use AJAX to replace a div ('#inviteform1') with a partial ('thankyou') after a form submission. For some reason, when the form is submitted, it's not working -- instead a blank screen appears, and the URL redirects to localhost:3000/inviterequests. What am I missing?
inviterequests_controller
def create
#inviterequest = Inviterequest.new(params[:inviterequest])
respond_to do |format|
format.js
end
end
inviterequests/create.js.erb
$("#inviteform1").hide().after('<%= j render("thankyou") %>')
inviterequests/_form.html.erb -- includes the div to be replaced
<%= simple_form_for(#inviterequest, html: { class: 'form-horizontal'}) do |f| %>
<% if #inviterequest.errors.any? %>
<div id="error_explanation">
<h3><%= pluralize(#inviterequest.errors.count, "error") %> prohibited this inviterequest from being saved:</h3>
<ul>
<% #inviterequest.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<!-- INVITE BOX CONTENT -->
<div class="invitebox">
<div class="invitebox-inner">
<div id="inviteform1">
<br> <br> <br>
<h5> INDIAN WEDDING <BR> PLANNING JUST GOT EASIER </h5>
<%= image_tag("smalldivider.png") %>
<h5> REQUEST AN INVITE </h5>
<div class="field">
<%= f.input :email, :placeholder => 'enter your email, please', label: false %>
</div>
<div class="actions">
<%= f.submit "SUBMIT", class: "btn btn-primary btn-special", remote: true %>
</div>
</div>
</div>
</div>
<% end %>
inviterequests/_thankyou.html.erb -- the partial to replace the div
<div id="thankyou">
<br> <br> <br>
<h3>THANK YOU </h3>
<h4> We are working hard to launch soon <br> and will be in touch. </h4>
<%= image_tag("smalldivider.png") %>
<p class="smallcaps"> <br> SHARE WITH FRIENDS IN THE MEANTIME </p>
<div class="socialbuttons">
<div class="twitter">
<%= link_to (image_tag("twitter2.png")), "https://twitter.com/intent/tweet?screen_name=namastewedding&text=is%20making%20Indian%20wedding%20planning%20easy.%20I%20just%20requested%20my%20invitation.%20%23indianwedding%20www.namastewedding.com", :target => '_blank' %>
</div>
<div class="facebook">
<%= link_to (image_tag("facebook2.png")), "https://www.facebook.com/pages/Namaste-Wedding/359192570873560" %>
</div>
</div>
</div>
LOGS
Started POST "/inviterequests" for 127.0.0.1 at 2013-08-29 22:08:39 -0400
Processing by InviterequestsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"pqDBzdaYKuOfjuVo1ovHvrQJTTrsUptAcQekCn4X+Ho=", "inviterequest"=>{"email"=>"foobar#gmail.com"}, "commit"=>"SUBMIT"}
Completed 406 Not Acceptable in 1ms (ActiveRecord: 0.0ms)
It seems that you should use remote: true in simple_form_for instead of f.submit.
Such as
<%= simple_form_for(#inviterequest, remote:true, html: { class: 'form-horizontal'}) do |f| %>

Categories

Resources