I am having trouble binding an ajax:error response to a form ID. Can someone point me in the right direction to solve this problem?
Here is the code.
<%= form_for #person,
html: {
id: '#person_form',
class: 'js_inline_validate'
},
data: { validate_url: validate_field_people_path },
remote: true,
url: people_path do |f| %>
<div class="form-group">
<div class='form-group-label'>
<%= f.label :first_name %>
</div>
<%= f.text_field :first_name,
:id => 'first_name',
class: 'js_new_person_frm_validate js_new_person_first_name' %>
<div class="text-error small">
<span>
<%= #person.errors.full_messages_for(:first_name).first if #person.errors[:first_name].any? %>
</span>
</div>
</div>
<div class="form-group">
<div class='form-group-label'>
<%= f.label :last_name %>
</div>
<%= f.text_field :last_name,
:id => 'last_name',
class: 'js_new_person_frm_validate js_new_person_last_name' %>
<div class="text-error small">
<span>
<%= #person.errors.full_messages_for(:last_name).first if #person.errors[:last_name].any? %>
</span>
</div>
</div>
<div class="form-group">
<%= f.submit "Create", data: { disable_with: false } %>
</div>
<% end %>
Controller
class PeopleController < ApplicationController
......
def create
#person = Person.new(create_params)
if(#person.save)
flash[:success] = "person created successfully"
redirect_to root_path
else
respond_to do |format|
format.html { render :action => 'new' }
format.any(:js, :json) {
render :json => { :error => #person.errors }, :status => 422
}
end
end
end
.....
end
CoffeeScript
$ ->
$("#person_form").on "ajax:error", (event, data, status, xhr) ->
alert "ajax:error!"
#do more stuff
The issue I cannot solve is this works as below when I use 'document', but I need this to be specific to my #person_form. And I get no response when I replace document with my form_id. Am I missing something simple here?
$ ->
$(document).on "ajax:error", (event, data, status, xhr) ->
alert "ajax:error!"
#do more stuff
Thank You!
I'm leaving this simple answer out here for anyone else who may run across this issue. Hopefully, it's this simple for the next person. It took me HOURS to track down the problem.
It turns out the error was happening because of a very simple mistake:
<%= form_for #person,
html: {
id: '#person_form', <= ERROR IS HERE!!
class: 'js_inline_validate'
},
data: { validate_url: validate_field_people_path },
remote: true,
url: people_path do |f| %>
The #person_form should have been person_form (excluding the pound sign). Just a very simple error in code I didn't catch when switching from script to ruby.
The global event handler would catch the ajax:error and execute the code properly. The pound sign in the identifier was preventing the proper registration of the local ajax event.
Related
I am trying to use JavaScript with jquery in rails to update a div without reloading the page. Its working but the comment is being created twice. I know something is wrong in the form partial but couldn't figure it out. Any help?
The following are the files -
_new_comment.html.erb
<%= form_for [:home, Comment.new], :url => home_comments_path, :html => {:id => "comment-new-" + post.id.to_s} do |f| %>
<div>
<%= f.text_area :message, :class => "message-area-" + post.id.to_s, :placeholder => "Add comment..." %>
<%= f.hidden_field :post_id, :value => post.id %>
<span class="new-comment"><%= link_to 'Add', '#', remote: true, :onclick => "$('#comment-new-#{post.id}').submit()" %></span>
</div>
<% end %>
comments_controller.rb
def create
#comment = Comment.new(comment_params)
#comment.user_id = current_user.id
if #comment.save
flash[:notice] = 'Comment added sucessfully'
respond_to do |format|
format.html { redirect_to home_posts_url }
format.js
end
end
end
create.js.erb
$("#comment-new-83").before('<div class="notice"><%= escape_javascript(flash[:notice]) %></div>');
$("#comment-new-83")[0].reset();
home.js
jQuery.ajaxSetup({
'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
$(document).ready(function() {
$("#comment-new-83").submit(function() {
$.post($(this).attr("action"), $(this).serialize(), null, "script");
return false;
})
})
form_for will automatically post to the controller. You need not submit the form explicitly using jquery.
Reference
Im trying to update my create item action to work with Ajax but Im getting an error of undefined methoditem_path` which i wasn't getting before when it was responding in regular html format. The item is created and saved but ajax doesn't seem to work properly though.
Here is my _from partial :
<%= form_for [#user, item], remote: true do |f|%>
<div class="form-group">
<%= f.label :name, class: 'sr-only' %>
<%= f.text_field :name , class: 'form-control', placeholder: "Enter a new item " %>
</div>
<%= f.submit "Submit Item", class: 'btn btn-primary pull-right' %>
<% end %>
item#create:
def create
#item = Item.new(item_params)
#item.user = current_user
if #item.save
flash[:notice] = 'Item saved successfully.'
else
flash[:alert] = 'Item not saved. Title is too short or missing. Please try again.'
end
respond_to do |format|
format.html
format.js
end
end
create.js.erb:
$('.js-items').prepend("<%= escape_javascript(render(#item)) %>");
$('.new-item').html("<%= escape_javascript(render partial: 'items/form', locals: {user: #user , item: #item }) %>");
User#show view
<div class='new_item'>
<%= render :partial => 'items/form', :locals =>{:item => Item.new , :user => #user} %>
</div>
<div class='js-items'>
<%= render #user.items %>
</div>
routes:
user_items GET /users/:user_id/items(.:format) items#index
POST /users/:user_id/items(.:format) items#create
new_user_item GET /users/:user_id/items/new(.:format) items#new
edit_user_item GET /users/:user_id/items/:id/edit(.:format) items#edit
user_item GET /users/:user_id/items/:id(.:format) items#show
PATCH /users/:user_id/items/:id(.:format) items#update
PUT /users/:user_id/items/:id(.:format) items#update
DELETE /users/:user_id/items/:id(.:format) items#destroy
The error im getting in rails s :
ActionView::Template::Error (undefined method `item_path' for #<#<Class:0x007fa4f0d30cd8>:0x007fa4f31b26b0>):
1: <%= form_for [#user, item], remote: true do |f|%>
2: <div class="form-group">
3: <%= f.label :name, class: 'sr-only' %>
4: <%= f.text_field :name , class: 'form-control', placeholder: "Enter a new item " %>
app/views/items/_form.html.erb:1:in `_app_views_items__form_html_erb__331698480542899910_70173200751480'
app/views/items/create.js.erb:2:in `_app_views_items_create_js_erb___3618987352886002527_70173200313760'
app/controllers/items_controller.rb:17:in `create'
Do something like that.
<%= form_for [#user, item], user_items, remote: true do |f|%>
If it doesn't work then run
rake routes
in terminal see what's your path.
I'm new to Rails and I have spent a good chunk of today struggling with the following issue. I'm integrating Stripe into my Rails application. All was going well until I try to actually finish the order and I get the following error in my local host
Stripe::InvalidRequestError in OrdersController#create
You must supply either a card or a customer id
I have tried various fixes all to no avail including disabling turbolinks on the whole app. I will really appreciate any help I can get since I'm not sure how to proceed from here. I have attached the relevant code below
Orders Controller
def create
#order = Order.new(order_params)
#place = Place.find(params[:place_id])
#seller = #place.user
#order.place_id = #place.id
#order.buyer_id = current_user.id
#order.seller_id = #seller.id
Stripe.api_key = ENV["STRIPE_API_KEY"]
token = params[:stripeToken]
puts "Token is #{token}"
begin
charge = Stripe::Charge.create(
:amount => (#place.rating * 100).floor,
:currency => "usd",
:card => token
)
flash[:notice] = "Thanks for ordering!"
rescue Stripe::CardError => e
flash[:danger] = e.message
end
respond_to do |format|
if #order.save
format.html { redirect_to root_url }
format.json { render :show, status: :created, location: #order }
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# FURTHER DOWN BELOW
private
def set_order
#order = Order.find(params[:id])
end
def order_params
params.require(:order).permit(:address, :city, :state, :card_number, :card_code, :'data-stripe' )
end
end
CoffeeScript
jQuery ->
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
payment.setupForm()
payment =
setupForm: ->
$('#new_order').submit ->
$('input[type=submit]').attr('disabled', true)
Stripe.card.createToken($('#new_order'), payment.handleStripeResponse)
false
handleStripeResponse: (status, response) ->
if status == 200
$('#new_order').append($('<input-type="hidden" name="stripeToken"/>').val(response.id))
$('#new_order')[0].submit()
else
$('#stripe_error').text(response.error.message).show()
$('input[type=submit]').attr('disabled', false)
Orders View
<div class="form-group">
<div class="row">
<div class="col-md-8">
<%= label_tag :card_number, "Credit Card Number" %>
<%= text_field_tag :card_number, nil, {:name => nil, :'data-stripe' => "number" , class: "form-control" } %>
</div>
<div class="col-md-4">
<%= label_tag :card_code, "CVC" %>
<%= text_field_tag :card_code, nil, {:name => nil, :'data-stripe' => "cvc" , class: "form-control" } %>
</div>
</div>
</div>
<div class="form-group">
<%= label_tag nil, "Expiration Date" %>
<div class="row">
<div class="col-md-3">
<%= select_month nil, { use_two_digit_numbers: true }, { :name => nil, :'data-stripe' => "exp-month", class: "form-control"} %>
</div>
<div class="col-md-3">
<%= select_year nil, { start_year: Date.today.year, end_year: Date.today.year+10 }, { :name => nil, :'data-stripe' => "exp-year", class: "form-control"} %>
</div>
</div>
</div>
Also upon another recommendation, I added the following
puts "Token is #{token}"
to the controller and I get
Token is _____
So I get a blank space in the terminal next to where the token is. Is the token not passing through here or what is going on?
Can anyone please help me to solve this? I'm not sure what to do anymore and I have spent the better half of today on this problem. Thank you!
The createToken method requires a JS object with number and expiry date values. I don't believe you're sending those to it. Try passing those explicitly, and putting breakpoints after the method in your browser debugger to see what happens.
I'm building a Rails app that takes credit cards and I'm trying to use Stripe to do it. I'm having some issues passing the data from my app to Stripe in order to charge. That's what I'm hoping to get help with on this topic.
First, I have a standard form (with values instead of placeholders for quick submitting for testing purposes). The form successfully enters the name and email into the DB and the customer's "plan" is hardcoded in the controller for the time being:
<%= form_for #customer do |f| %>
<div class="payment-errors"></div>
<div class="name field">
<%= f.label :name %>
<%= f.text_field :name, :value => "Your name" %>
</div>
<div class="email field">
<%= f.label :email %>
<%= f.text_field :email, :value => "yourname#example.com" %>
</div>
<div class="cc_number field">
<%= label_tag 'cc_number' %>
<%= text_field_tag 'cc_number', nil, :value => "4242424242424242" %>
</div>
<div class="ccv field">
<%= label_tag 'ccv' %>
<%= text_field_tag 'ccv', nil, :value => "123" %>
</div>
<div class="cc_expiration field">
<%= label_tag 'cc_month', "Expiration date" %>
<%= text_field_tag 'cc_month', nil, :value => "12" %>
<%= text_field_tag 'cc_year', nil, :value => "2012" %>
</div>
<div class="actions">
<%= f.submit "Continue", :class => 'btn' %>
</div>
<% end %>
Also in my signups_view where the above code is, I have this JS, mostly provided by Stripe:
<script type="text/javascript">
// this identifies your website in the createToken call below
Stripe.setPublishableKey('<%= STRIPE['public'] %>');
function stripeResponseHandler(status, response) {
if (response.error) {
// show the errors on the form
$(".payment-errors").text(response.error.message);
$("input[type=submit]").removeAttr("disabled");
} else {
var form$ = $("form");
// token contains id, last4, and card type
var token = response['id'];
// insert the token into the form so it gets submitted to the server
form$.append("<input type='hidden' name='customer[stripe_token]' id='stripeToken' value='" + token + "'/>");
// and submit
$('.cc_number.field, .ccv.field, .cc_expiration.field').remove();
form$.get(0).submit();
}
}
$(document).ready(function() {
$("form").submit(function(event) {
// disable the submit button to prevent repeated clicks
$('input[type=submit]').attr("disabled", "disabled");
Stripe.createToken({
number: $('#cc_number').val(),
cvc: $('#ccv').val(),
exp_month: $('#cc_month').val(),
exp_year: $('#cc_year').val()
}, stripeResponseHandler);
// prevent the form from submitting with the default action
return false;
});
});
</script>
There seems to be a problem with the line form$.append("<input type='hidden' name='customer[stripe_token]' id='stripeToken' value='" + token + "'/>");, as my Ruby app breaks when it gets to customer[stripe_token].
Finally, in my `customers_controller`, I have:
def create
#customer = Customer.new(params[:customer])
#customer.product =
if #customer.save
save_order
redirect_to #customer
else
render action: 'new'
end
def save_order
Stripe.api_key = STRIPE['secret']
charge = Stripe::Charge.create(
:amount => 20,
:currency => "usd",
:card => #customer.stripe_token,
:description => "Product 1"
)
end
Whenever I submit the form, it hits the else clause in the controller each time and after plenty of debugging, Googling around and stripping out this from and rebuilding from scratch, I'm still stumped.
Any help would be very very much appreciated.
Edit: Added the customer model
attr_accessible :name, :email, :stripe_token, :product
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, :presence => true,
:format => { :with => email_regex },
:length => { :minimum => 6, :maximum => 60 },
:uniqueness => { :case_sensitive => false }
validates :name, :length => {:minimum => 2, :maximum => 80 }
It would help to see your Customer model to get an idea of what's going on. If #customer.save returns false, it means that a validator is likely failing.
Also, do you have stripe_token as an accessible attribute on your model? Otherwise you won't be able to assign it form the form like you're doing. Note that the token should not be stored in the database, since it can only be used once.
class Customer
attr_accessor :stripe_token # do you have this?
end
One more note: you will probably want to store a Stripe ID field so that you can retrieve customer payments and cancel their account later.
I'm trying to use jQuery Tokeninput as shown in Railscast #258 (revised). When I enter something in the tokeninput field, the field does not dropdown with results and I get the following javascript error: Uncaught TypeError: Cannot call method 'replace' of undefined.
My json data works fine when I do a manual query on it, and the server request looks fine. I am trying to search the content column in my issues table, so I set propertyToSearch to "content".
Here is my code:
coffeescript:
jQuery ->
$('#fact_issue_tokens').tokenInput "/issues.json"
theme: 'facebook'
zindex: 11001
propertyToSearch: 'content'
tokenValue: 'content'
hintText: 'Enter an issue'
preventDuplicates: true
Issue Model:
def self.tokens(query)
issues = where("content like ?", "%#{query}%")
if issues.empty?
[{id: "<<<#{query}>>>", content: "New: \"#{query}\""}]
else
issues
end
end
def self.ids_from_tokens(tokens)
tokens.gsub!(/<<<(.+?)>>>/) { create!(content: $1).id }
tokens.split(',')
end
Issues Controller:
def index
#issues = Issue.order(:content)
respond_to do |format|
format.html
format.json { render json: #issues.tokens(params[:q]) }
end
end
Form:
<%= form_for(Fact.new, :url => kase_facts_path(current_kase), :html => {:class => "form-
inline"}) do |f| %>
<%= f.text_field :page, placeholder: 'Page' %>
<%= f.text_field :description, placeholder: 'Description' %>
<%= f.label :issue_tokens, 'Issue tags' %>
<%= f.text_field :issue_tokens %>
<%= f.hidden_field :source_id, :value => #source.id %>
<%= f.submit 'Add Fact' %>
<% end %>
#Scott you try this
jQuery ->
$('#fact_issue_tokens').tokenInput '/issues.json'
theme: 'facebook'
tokenLimit: 5
minChars: 4
preventDuplicates: true
searchingText: "Enter an issue..."
prePopulate: $('#fact_issue_tokens').data('load')
and think on your index because you are using (:content) not name might be your problem. I am bot sure why but i used title and i had a problem, i thought it was mysql or something.
When you visit
http://localhost:3000/issues.json
Do you get the JSON data?
Edit.
Can you please try this for your form?
<div class="field">
<%= f.label :issue_tokens, "Issues" %><br />
<%= f.text_field :issue_tokens, data: {load: #fact.issues} %>
</div>