Rails/Ajax/ jQuery: Pass multiple params from jquery to Rails controller - javascript

I need to pass two params (selected option & selected number of persons) from radio buttons through jquery to Rails controller via ajax and would appreciate any help at all on how to do so. Both params are needed to calculate pricing (please see #price code in controller below) and right now I'm only able to pass one param at a time for the calculation.
My form html code is shown below:
<%= form_for #cartedactivity, url: carted_activities_path, method: :post, remote: true do |f| %>
1. Choose option
<div class = "options">
<center>
<% #options.each do |option| %>
<div class = "radio" id = "option_radio">
<%= f.radio_button :supplier_activity_option_id, option.id, :onclick => "save_option();" %>
<%= f.label :supplier_activity_option_id, option.option_name, :value => option.id %>
</div>
<% end %>
</center>
</div>
<h5>2. Number of Persons</h5>
<div class = "numbers">
<center>
<h5>
<%#numbers.each do |number| %>
<div class = "radio" id =
"quantity_radio">
<%= f.radio_button :activity_quantity, number, :onclick => "save_quantity();" %>
<%= f.label :activity_quantity, number, :value => number %>
</div>
<% end %>
</h5>
</center>
</div>
<h5>3. Start date
<%= f.date_field :activity_date, min: (Date.today+2.days), max: (Date.today+4.months)%>
</h5>
<hr>
<div id = "check-price-<%=#option%>"></div>
<div class = "booking-btn">
<%= f.submit "Add to Cart", class: "btn btn-book" %>
</div>
<% end %>
</div>
</div>
<br><br>
<script>
function save_option()
{var optionValue = $('input[name = "carted_activity[supplier_activity_option_id]"]:checked').val();
if (optionValue) {
$.ajax({
type: "POST",
url: "/supplier_activities/price_check",
data: { optionValue },
success: function(post){ console.log('success') },
error: function(post){ console.log(this) }
});
}
};
function save_quantity()
{var quantityValue = $('input[name = "carted_activity[activity_quantity]"]:checked').val();
if (quantityValue) {
$.ajax({
type: "POST",
url: "/supplier_activities/price_check",
data: { quantityValue },
success: function(post){ console.log('success') },
error: function(post){ console.log(this) }
});
}
};
The partial html is simply <% #price %>
The controller code is :
def price_check
#option = params[:optionValue]
#number = params[:quantityValue]
if !#option.blank? && !#number.blank?
#price = Price.find_by("supplier_activity_option_id = ? AND min_qty_for_price <= ? AND max_qty_for_price >= ?", params[:optionValue], params[:quantityValue], params[:quantityValue]).price_usd
else
#price = 100
end
respond_to do |format|
format.js {render layout: false}
end
end

Found the solution - have passed through the value of both checked radio buttons on each click of any radio button. This means that whenever a radio button is clicked, the values of both checked buttons are passed in at the same time.
<script>
function save_option()
{var optionValue = $('input[name = "carted_activity[supplier_activity_option_id]"]:checked').val();
var quantityValue = $('input[name = "carted_activity[activity_quantity]"]:checked').val();
if (optionValue) {
$.ajax({
type: "POST",
url: "/supplier_activities/price_check",
data: { optionValue: optionValue, quantityValue: quantityValue },
success: function(post){ console.log('success') },
error: function(post){ console.log(this) }
});
}
};
function save_quantity()
{var quantityValue = $('input[name = "carted_activity[activity_quantity]"]:checked').val();
var optionValue = $('input[name = "carted_activity[supplier_activity_option_id]"]:checked').val();
if (quantityValue) {
$.ajax({
type: "POST",
url: "/supplier_activities/price_check",
data: { quantityValue: quantityValue, optionValue: optionValue },
success: function(post){ console.log('success') },
error: function(post){ console.log(this) }
});
}
};
</script>

Related

How to access Rails model attributes inside JavScript?

<%= form_for(#mymodel, remote: true, html: { id: 'match_form' }) do |f| %>
<!-- I need to check if #mymodel.match_id matches the value generated by a controller function -->
<%= f.submit 'Save', class: 'btn btn-primary', id: 'match_submit', style: "width:38px;padding:0px" %>
<%= button_tag 'Cancel', class: 'btn btn-secondary', id: 'match_cancel', style: "width:52px;padding:0px" %>
<% end%>
<script type='text/javascript'>
$(function() {
$(document).on("click", "#match_submit", function(event){
$.ajax('my_controller_method', {
type: 'GET',
dataType: 'script',
data: {
mid: $("#").val(), // how do I pass #mymodel.match_id here?
},
error: function(jqXHR, textStatus, errorThrown) {
return console.log("AJAX Error: " + textStatus);
}
});
});
</script>
I have a Rails form that represents a model as shown above.
How can I access attributes of the model inside the JavaScript code block shown above?
You can use erb inside of javascript too:
mid: <%= #mymodel.match_id %>,
Or you can serialize your object with gon gem (https://github.com/gazay/gon)

Rails error messages in login form with AJAX

I think I've got complicated problem but let's keep it simple. I'm using devise and I want to show error message below form in my login page. Right now when user provide wrong password in console I've got an error POST 401 (Unauthorized) but errors didn't showed up in a page.
slice_code.js.erb
$(document).ready(function() {
var form = $('.centralized-login')
form.submit( function(event) {
event.preventDefault()
var email = $('#email-input').val()
var password = $('#password-input').val()
var req = $.ajax('/user_role', {
data: {
email
}
})
req.then( function(result) {
var { role } = result
switch (role) {
case 'company_manager':
$.ajax('/users/sign_in', {
method: "POST",
data: {
"user[email]": email ,
"user[password]": password,
"authenticity_token": $('input[name="authenticity_token"]').val()
},
success: function(data, textStatus, req){
window.location="/users/sign_in"
}
})
break;
should I add something like $("ajax:error") ?
_new.html.erb
<div class="col-sm-8 col-md-6 col-xs-12">
<div class="vr-textfield-wrapper">
<%= f.email_field :email, id: "email-input", class: "vr-textfield", placeholder: t('users.passwords.new.email_placeholder'), required: true, aria_required: true, autofocus: true %>
<span class="vr-field__invalid-msg"><%= t 'users.passwords.new.valid_email'%></span>
<% if resource.errors.full_messages_for(:email).first %>
<div class="vr-textfield-wrapper">
<div class="alert alert-danger">
<div class="error-explanation">
<%= t('activerecord.errors.models.user.attributes.email.not_found_in_database') %>
</div>
</div>
</div>
<% end %>
</div>
</div>
Edit
success: function(data, textStatus, req){
window.location="/users/sign_in"
},
error: function (jqXHR, textStatus, errorThrown) {
$('.centralized-login').find('.error-explanation').html(errorThrown)
console.log(textStatus + " " + errorThrown);
}
})
sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
include LogoutUsergroups
def after_sign_out_path_for(_user)
new_user_session_path
end
end
You can render the error in the js response(create.js.erb) of view file itself. something like below,
<%- if resource.errors.any? %>
var id = $('form#Id') <!-- Replace with your selector -->
<% resource.errors.each do |key, value| %>
id.find('selector').html("<%= "#{key.to_s.humanize} #{value}" %>");
<% end %>
<%- end %>
Or you could use the error function as like you used the success function,
$.ajax({
success: function(data, textStatus, req){
window.location="/users/sign_in"
}
error: function (jqXHR, textStatus, errorThrown) {
id.find('selector').html(""); # Use the error here to show in the UI.
console.log(textStatus + " " + errorThrown);
}
});
$("ajax:error") should be used when using the remote: true for form submit. For reference: https://github.com/rails/jquery-ujs/wiki/ajax

Rails: remote: true from select_tag

I'm calling an AJAX function from a select_tag like so:
<%= select_tag 'quantity', options_from_collection_for_select(order.options), :quantity, :quantity, order.quantity), onchange: "update_price(#{order.id}, this.value);" %>
And here's the function:
<script type='text/javascript'>
function update_price(order_id, quantity) {
$.ajax({
url: "/cart/" + <%= #cart_transaction.id %> + "/update_quantity",
type: "POST",
data: {
"order_id" : order_id,
"quantity" : quantity },
dataType: "html"
});
}
</script>
My .js.erb isn't called ever, and I suspect it's because I haven't specified remote: true anywhere, but since I don't have a form per se I don't know how to do that. Any help?
Relevant controller code here:
class CartTransactionsController < ApplicationController
load_and_authorize_resource
respond_to :html, :js
before_filter :set_cart_transaction
def update_quantity
#order = #cart_transaction.orders.find(params[:order_id])
#price = current_user.brand.prices
.where(template_id: #order.document.template.id)
.where(quantity: params[:quantity]).first
#order.update_attributes(
price_cents: #price.amount_cents, quantity: params[:quantity]
)
#cart_transaction.save!
respond_to { |format| format.js }
end
private
def set_cart_transaction
#cart_transaction = current_user.cart
end
def cart_transactions_params
params.require(:cart_transaction).permit(
:name, :email, :delivery_address, :comments
)
end
end
Update
Here's the .js.erb that isn't called for some reason:
console.log("update_quantity.js.erb file");
$('#price_cell').html("<%= j render(partial: 'price', locals: { order: #order }) %>");
$('#subtotals').html("<%= j render(partial: 'subtotals', locals: { cart_transaction: #cart_transaction }) %>");
Try this:
function update_price(order_id, quantity) {
$.ajax({
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
},
url: "/cart/" + <%= #cart_transaction.id %> + "/update_quantity",
type: "POST",
data: {
"order_id" : order_id,
"quantity" : quantity }
});
}
Use dataType: "script", it will work and will render js.erb

How to access an instance variable inside JavaScript?

I have the following controller actions:
def new
#tag = Tag.new({company_id: current_member.company_id })
end
def create
#tag = Tag.new(tag_params)
#companyid = current_member.company_id
respond_to do |format|
if #tag.save
format.html {redirect_to root_path}
format.json {render :json=> #tag}
else
format.html {redirect_to root_path}
end
end
end
Inside my new.html.slim view file I have:
= simple_form_for #tag, url: tags_new_path, html: {id:'tag_form_submit', method: :post}, format: :js, remote:true do |t|
=t.input :name, placeholder: 'tag'
=t.button :submit, "submit tag", id:"submit_tag_button"
javascript:
$(document).ready(function(){
$("#submit_tag_button").click(function(event){
event.preventDefault();
<!-- $("#tag_form_submit").hide(); -->
<!-- $('#add_tag_tag').hide(); -->
var text = $("#inputbox").val();
var name = $("#tag_name").val();
var datatosend = { tag: {name:name, company_id: "#{#companyid}" } };
$.ajax({
url: "/tags/new",
dataType: "json",
method: "post",
data: datatosend,
success: function(result){
console.log(result)
var nameVar=result.name;
var idVar=result.id;
console.log(nameVar);
console.log(idVar);
var newspan='<span class="checkbox"><label for="job_tag_ids_'+idVar+'" name="job[tag_ids]"><input class="check_boxes optional form-control" data-remote="true" id="job_tag_ids_'+idVar+'" name="job[tag_ids][]" type="checkbox" value="'+idVar+'">' + nameVar + '</label></span>';
$("#all_tags > div.form-group.check_boxes.optional.job_tags > div").append(newspan);
<!-- $(#event_tag_ids).append('hi'); -->
if ($("#event_tag_ids").length){
$("#event_tag_ids").append('<option value="'+idVar+'">'+nameVar+'</option>');
}
// after its appended, erase from form input
console.log(result.company_id);
$("#tag_name").val("");
}
})
})
});
In my datatosend varible I am trying to send:
var datatosend = { tag: {name:name, company_id: "#{#companyid}" } };
but #companyid is being posted as null. Why?
How do I successfully access #companyid from the controller inside my JavaScript so I can send it in when making my AJAX post call?
You're only assigning the #companyid instance variable in the create action of your controller, not the new action.
The view template you posted is rendered as part of the new action. So you should change your controller:
def new
#companyid = current_member.company_id
#tag = Tag.new(company_id: #companyid)
end

Updating vote counter rails ajax request

I have a rails app, in which my Posts model has Comments and the comments are votable. I'm using acts_as_votable.
I currently have the voting on the comments working. Now I'm trying to implement some javascript so that the page does not have to refresh every time someone votes on a comment, so that the vote goes through.
This is what I have in my comments controller:
def upvote_post_comment
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.liked_by current_user
respond_to do |format|
format.html {redirect_to :back }
format.json { render json: { count: #comment.votes.size } }
end
end
And this is what I have in my view:
<% if user_signed_in? && current_user != comment.user && !(current_user.voted_for? comment) %>
<%= link_to image_tag(‘vote.png'), like_post_comment_path(#post, comment), method: :put, class: 'vote', remote: true, data: { type: :json } %>
<a><%= "#{comment.votes.size}"%></a>
<script>
$('.vote')
.on('ajax:send', function () { $(this).addClass('loading'); })
.on('ajax:complete', function () { $(this).removeClass('loading'); })
.on('ajax:error', function(e, xhr, status, error) { console.log(status); console.log(error); })
.on('ajax:success', function (e, data, status, xhr) { $(this).html(data.count); });
</script>
<% elsif user_signed_in? && (current_user = comment.user) %>
<%= image_tag(‘voted.png')%><a><%= "#{comment.votes.size}"%></a>
<% else %>
<%= image_tag(‘voted.png')%><a><%= "#{comment.votes.size}"%></a>
<% end %>
When I click on the vote.png icon, the icon disappears and the vote count shows up instead of it. How do I get the vote.png icon to change to the voted.png icon and the vote count to update within the designated placeholder?
<a><%= "#{comment.votes.size}"%></a>
The rendered HTML:
<p>
<p>comment test</p>
<a class="vote" data-method="put" data-remote="true" data-type="json" href="/1/comments/8/like" rel="nofollow">
<img src="/assets/vote.png" />
<span>0</span>
</a>
</p>
The simple answer:
You're updating your entire .vote element (including your image). You need to differentiate between .vote img and .vote span:
<%= link_to like_post_comment_path(#post, comment), method: :put, class: 'vote', remote: true, data: { type: :json } do %>
<%= image_tag(‘vote.png') %>
<%= content_tag :span, comment.votes.size %>
<% end %>
.on('ajax:success', function (e, data, status, xhr) { $(this).find('span').html(data.count); }
Re-Factored Answer
#app/assets/javascripts/application.js
$(document)
.on('ajax:send', '.vote', function () { $(this).addClass('loading'); })
.on('ajax:complete', '.vote', function () { $(this).removeClass('loading'); })
.on('ajax:error', '.vote', function(e, xhr, status, error) { console.log(status); console.log(error); })
.on('ajax:success', '.vote', function (e, data, status, xhr) { $(this).find("span").html(data.count); });
#view
<% if user_signed_in? && current_user != comment.user %>
<% if !(current_user.voted_for? comment) %>
<%= link_to like_post_comment_path(#post, comment), method: :put, class: 'vote', remote: true, data: { type: :json } do %>
<%= image_tag('vote.png') %>
<%= content_tag :span, comment.votes.size %>
<% end %>
<% else %>
<%= image_tag('voted.png')%><a><%= "#{comment.votes.size}"%></a>
<% end %>
<% end %>
You're replacing your vote.png on your on success call.
.on('ajax:success', function (e, data, status, xhr) { $(this).html(data.count); });
Replace "this" with the class of your comment.votes.size.

Categories

Resources