Rails: How to catch ajax success - javascript

I googled a lot and was unable to find my mistake. As I just started with JS this might be an easy one. Using: Rails 4
I have a modal with a form that I would like to do stuff after successfully (or not) doing the ajax call. For now just closing the modal.
modal (this works actually works, so I can edit stuff):
.modal.fade{ id: attribute.id, role: 'dialog', tabindex:'-1' }
.modal-dialog{ role: 'document'}
.modal-content
.modal-header
%button{ type: 'button', class: 'close', 'data-dismiss' => "modal" }
%span ×
%h4.modal-title= attribute.name
= form_for attribute, remote: true, html: { class: 'form-inline', id: 'edit_form' } do |f|
.modal-body
.form-group
= f.label :name, 'Name', class: 'form-label', style: 'width: 150px'
= f.text_field :name, class: 'form-control', style: 'width:200px;margin-right: 35px'
.modal-footer
%button{ type: "button", class: "btn btn-default pull-left", 'data-dismiss' => "modal" }
Close
= f.submit 'Create', class: 'btn btn-primary pull-right'
my JS file (dont laugh):
$(document).ready( function($) {
console.log('ready'); # this I *can* see in the console
$('#edit_form').bind("ajax:success", function() {
console.log('great success') # this I *can't* see in the console.
});
});
controller (additional fun fact: The modal is triggered in a view for a different controller, not the one of the modal that I am actually trying to change):
respond_to do |format|
format.js {}
end
So in the end I would like to catch the "error" and "success" callbacks and do sth with it (this I am trying to figure out myself first). What am I doing wrong here?
Thanks a lot for your help - it is really appreciated!

According to the answer of a similar question you might want to try:
$('#edit_form').on("ajax:success", ...
// ^-- instead of .bind
I assume you also have a recent jQuery version, so give this change a shot.

Related

How to call a javascript function in a rails form?

I have a rails form that looks like this :
= form_for :location, :url=>'/welcome' do |f|
= f.text_field '', placeholder: 'Enter your zip code', id:'input_id'
= f.button "Continue", class: 'button-test'
So when the button continue is clicked upon , rails get the controller and execute the method /welcome
so what i am trying to do is to actually execute a simple javascript function like :
function wawa() {
alert('it works')
};
when the button continue is cliked instead of rails getting to execute the method /welcome.
How can I approach this problem using Javascript only and no library ?
You can use submit() function of jquery.
= form_for :location, :url=>'/welcome', html: {id: "id_form_location"} do |f|
= f.text_field '', placeholder: 'Enter your zip code', id:'input_id'
= f.button "Continue", class: 'button-test'
In javascript file:
$("#id_form_location").submit(function(event) {
alert('it works');
});
You need to add some JavaScript On submit Listener I suppose you need it before form is submit. If you want only on click then have a look at on click Listener also have a look at event prevent as it will help you to prevent from default behaviour of button.
Try this code
<%= form_for :location, :url=>'/welcome' do |f| %>
<%= f.text_field '', placeholder: 'Enter your zip code', id:'input_id' %>
<%= f.button "Continue", class: 'button-test', id: 'demo' %>
<% end %>
<script type="text/javascript">
document.getElementById("demo").addEventListener("click", function(event){
event.preventDefault()
alert('Hello')
});
</script>

Completing items in ruby on rails 4

I have migrated a :completed boolean, I then added it to my form like so (simple_form)
<%= f.input :completed, as: :boolean %>
This allows me to update completed, not completed in the edit view.
How can I edit the :completed method in my index view? I want to be able to update complete or not complete on the fly.
EDIT:
My Form
<%= f.input :completed, as: :boolean, input_html: { class: 'completed', id: #todo.id } %>
My View (label has to be after input as per materializecss)
<%= check_box_tag todo.id, 'completed', todo.completed?, class: 'completed' %>
<label class="strikethrough">
COMPLETE
</label>
The JS
// This could be other events as well, so add/change/remove the event trigger as needed
$(document).on('click', '.completed', function(){
updateCompleted($(this));
});
function updateCompleted($el) {
var id = $el.attr('id'),
val = $el.is(':checked');
$.PATCH({
url: '/todos/'+id,
data: { todo: { completed: val } },
success: function(){ whatever },
error: function() { whatever }
});
}
My Controller
params.require(:todo).permit(:title, :item, :image, :completed)
You are going to require some AJAX here. In my experience, doing this is a bit outside of the "rails way", but totally possible.
First, make sure you have the ID of the object somewhere in the dom:
<%= f.input :completed, as: :boolean, input_html: { class: 'completed', id: myobject.id %>
I used the simple_form syntax since that's what it appears you are using for your form builder. If not, comment back and I'll adjust the tag.
Secondly, add a jquery event listener:
// This could be other events as well, so add/change/remove the event trigger as needed
$(document).on('click', '.completed', function(){
updateCompleted($(this));
});
function updateCompleted($el) {
var id = $el.attr('id'),
val = $el.is(':checked');
$.PATCH({
url: '/your_endpoint/'+id,
data: { your_object_name: { completed: val } },
success: function(){ whatever },
error: function() { whatever }
});
}
And in your controller:
private
def your_object_params
params.require(:your_object).permit(..., :completed)
end
That's basically it.
Basically you will want to make a post to the update action from the index action. I would use JavaScript but you can also use a hard refresh if you want to stick with rails. Here is a good intro if you are not familiar with using JS in your rails app. http://railscasts.com/episodes/324-passing-data-to-javascript.

Rails Simple Form Bootstrap - Javascript if statement to reveal input

I have a rails 4 app with simple form and bootstrap.
I want to ask a question in my form which asks whether users need survey responses. If the answer to that is true, then I want to ask a follow up question. My two survey questions are:
<%= f.input :survey, :as => :boolean, :label => false, inline_label: 'Do you need survey responses?' %>
<br><br>
<%= f.input :survey_link, label: 'Where is your survey?', :label_html => { :class => 'question-data' }, placeholder: 'Include a link to your survey', :input_html => {:style=> 'width: 650px; margin-top: 20px', class: 'response-project'} %>
Is JS if statement the best way to approach this task? I want to hide the second question until the user answers true to the first question.
If so, I'm having trouble understanding how to make this JS work.
I have tried:
if (:survey is :true) {
:survey_link;
}
I can't find any resources to help explain how to do this. Help would be very much appreciated. Thank you.
Obviously the code below depends on what the name of your survey and survey_link inputs look like in actual HTML. So if in this example it is for #user:
<% simple_form_for #user do |f| %>
<%= f.input :survey, :as => :boolean, :label => false, inline_label: 'Do you need survey responses?' %>
<%= f.input :survey_link, label: 'Where is your survey?', :label_html => { :class => 'question-data' }, placeholder: 'Include a link to your survey', :input_html => {:style=> 'width: 650px; margin-top: 20px', class: 'response-project'} %>
<% end %>
Then the JQuery should look like (note the user part - you may have to change this):
<script>
$(function() {
// Hide the survey_link input
$('input[name="user[survey_link]"]').hide();
$('input[name="user[survey_link]"]').closest("label").hide();
// When the survey checkbox changes
$('input[name="user[survey]"]').change(function() {
$('input[name="user[survey_link]"]').closest("label").toggle(this.checked);
$('input[name="user[survey_link]"]').toggle(this.checked);
});
});
</script>

Coffeescript not completing but no error

I've having trouble with the following coffeescript:
jQuery ->
# Create a comment
$(".comment-form")
.on "ajax:beforeSend", (evt, xhr, settings) ->
$(this).find('textarea')
.addClass('uneditable-input')
.attr('disabled', 'disabled');
.on "ajax:success", (evt, data, status, xhr) ->
$(this).find('textarea')
.removeClass('uneditable-input')
.removeAttr('disabled', 'disabled')
.val('');
$(xhr.responseText).hide().insertAfter($(this)).show('slow')
# Delete a comment
$(document)
.on "ajax:beforeSend", ".comment", ->
$(this).fadeTo('fast', 0.5)
.on "ajax:success", ".comment", ->
$(this).hide('fast')
.on "ajax:error", ".comment", ->
$(this).fadeTo('fast', 1)
Basically, I have a user form that I add comments to. When a new comment is added it should change class and disable the textarea before sending the data off to the database. Then it should reset the class, clear the textarea and enable the textarea again. Then finally it should add the new comment after the textarea.
The first part of the code works and the class is added to the textarea and it is set to disabled but the rest of the script never happens. Of course the comment is actually saved to the database and a refresh of the page will show the comment.
I've gone over this a ton of times and can't figure out what is going wrong. I did have an earlier issue with the indenting being wrong with the script but that has been fixed.
My CommentController code is as below:
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :destroy]
def create
#comment_hash = comment_params
#obj = #comment_hash[:commentable_type].constantize.find(#comment_hash[:commentable_id])
# Not implemented: check to see whether the user has permission to create a comment on this object
#comment = Comment.build_from(#obj, current_user, #comment_hash[:body])
#comment.user = current_user
if #comment.save
render partial: "comments/comment", locals: { comment: #comment }, layout: false, status: :created
else
p #comment.errors
render js: "alert('error saving comment');"
end
end
def destroy
if #comment.destroy
render json: #comment, status: :ok
else
render js: "alert('error deleting comment');"
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_comment
#comment = Comment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit( :commentable_id, :commentable_type, :body, :user_id)
end
end
Here's my form for creating comments:
<div class='comment-form'>
<%= simple_form_for comment, remote: true do |f| %>
<%= f.input :body, input_html: { rows: "2" }, label: false %>
<%= f.input :commentable_id, as: :hidden, value: comment.commentable_id %>
<%= f.input :commentable_type, as: :hidden, value: comment.commentable_type %>
<%= f.button :submit, 'Save Note', class: "button tiny radius", disable_with: "Submitting…" %>
<% end %>
</div>
And here's my code for displaying comments:
<div class='comment'>
<hr>
<%=link_to "×", comment_path(comment), method: :delete, remote: true, data: { confirm: 'Are you sure you want to remove this comment?',disable_with: 'x' }, class: 'close' %>
<small><%=comment.updated_at.to_s(:short) %></small>
<p><%= comment.body %></p>
By the way, the delete action partially works. It deletes the comment from the database and it hides all of the comments. A page refresh shows the comments that have not been deleted.
Any help would be greatly appreciated since I don't know where to go with this not at all. In my mind it should work so I must be missing something simple.
It's an issue with your indentation. The line .on "ajax:success" must be indented at the same level as the other .on. And the code that follows must be indented accordingly as well:
jQuery ->
# Create a comment
$(".comment-form")
.on "ajax:beforeSend", (evt, xhr, settings) ->
$(this).find('textarea')
.addClass('uneditable-input')
.attr('disabled', 'disabled');
.on "ajax:success", (evt, data, status, xhr) -> #<-- this line!
$(this).find('textarea')
.removeClass('uneditable-input')
.removeAttr('disabled', 'disabled')
.val('');
$(xhr.responseText).hide().insertAfter($(this)).show('slow')

Autocomplete with typeahead in rails 3

I'm developing autocomplete for a particular form in my rails app; for this purpose I'm using typeahead.js with custom controller method. So far, it works but I need using those values within the form again so that I can press the submit button and the form will be posted and processed by rails normally. How can I do this? Here's the code right now
.page-header
%h1
= #org.name
%small= t('.title')
= form_for #org_admin, |
url: organization_organization_admins_path(#organization) do |f|
.form-group
= f.label t('.user')
= f.hidden_field :user, id: 'user_id'
%input.typeahead{ :type => "text", :autocomplete => "off"}
= f.submit t('.submit'), class: 'btn btn-primary'
= link_to t('.back'), organization_organization_admins_path(#organization)
:javascript
$(document).ready(function() {
$('input.typeahead').typeahead({
name: 'names',
remote: "#{search_organization_organization_admins_path(#organization)}?term=%QUERY",
engine: Hogan,
template: '<p><strong>{{username}}</strong></p>',
limit: 10
}).on('typeahead:selected', function(e, data){
$('#user_id').value = data.id
});
});
So, I would like to populate the :user attribute in the form with the json object returned by the controller
Nevermind, I figured out... the above code is in the right path, except for the call to this line
$('#user_id').value = data.id
Since I'm using jQuery to select the hidden element I had to use the jQuery val function instead
$('#user_id').val(data.id)

Categories