Passing a string to an object in controller using ajax - javascript

I'm new to web programming. So I've been searching on the web for awhile to solve this on my own, but there seems to be no one who has similar problems.
In my program, I am getting user input that contains the admins for a new booth that's being created through a textarea in my app/views/booths/new.html.erb file, as shown below.
app/views/booths/new.html.erb :
<% provide(:title, 'Create New Booth') %>
<h1>Create New Booth</h1>
<% javascript_include_tag "booths" %>
<div>
<div>
<%= form_for(#booth) do |f| %>
<%= f.label :booth_name, "Name of the new Booth" %>
<%= f.text_field :booth_name %>
<%= f.label :booth_description, "Describe your new Booth" %>
<%= f.text_field :booth_description %>
<%= f.label :important_notice, "Any important notices?" %>
<%= f.text_field :important_notice %>
<span><br>Admins for this Booth?<br> </span>
<textarea id="create_booth_admins_textarea" rows="30" cols="50"> </textarea>
<%= f.submit "Create a new booth", :id => "booth_create_submit"%>
<% end %>
</div>
</div>
app/assets/javascripts/booths.js excerpt:
admins = $("textarea#create_booth_admins_textarea").val();
$('#booth_create_submit').click(function() {
$.ajax({
url: "/booths_create",
data: { "booth_admin_emails" : admins},
type: "post",
cache: false,
success: function () {
console.log("ajax successful");
alert("ajax successful");
},
error: fucntion() {
console.log("ajax error");
alert("ajax error")
}
});
});
app/controller/booths_controller.rb :
def new
#booth = Booth.new
#other_members = []
#booth_admins = []
end
def create
temp_hash = booth_params
#booth = Booth.new(temp_hash.except(:booth_admin_emails))
#booth.admin_id = current_user.id #fill in the Booth table
#booth_admins = temp_hash[:booth_admin_emails]
booth_admins = []
if #booth.save
#fill in join table
BoothUser.create(:user_id => current_user.id, :booth_id => #booth.id, :is_admin => true) #add current user
if !#booth_admins.nil?
booth_admins = #booth_admins.split(",")
end
if !booth_admins.empty?
booth_admins.each do |email|
BoothUser.create(:user_id => User.where("email=?", email).id, :booth_id => #booth.id, :is_admin => true)
end
end
# just a flash to tell user that new booth was created
name = #booth.booth_name
flash[:success] = "New Booth #{name} created!"
redirect_to '/booths'
else
render('show')
end
end
private
def booth_params
params.require(:booth).permit(:booth_name, :booth_description, :important_notice, :booth_admin_emails)
end
User and Booth are of has_many through association, where the join table is called BoothUser, which contains information of the booth_id, user_id, is_admin, where the id are the indicies of the specific user and the booth in their respective tables and is_admin is a boolean value checking whether the user is an admin (has the permission to edit booth settings) of the booth.
The problem arises because in my Booth table, I only declare the creator of the booth, and do not track the given admins for that booth, but am trying to find these admins for that booth by looking up the join table where the booth_id matches the index of that booth and is_admin is true.
I have been trying to pass what's being input on the create_booth_admins_textarea to :booth_admin_emails in the controller but so far had no luck, as nothing was passed onto the :booth_admin_emails. I'm guessing it's because :booth_admin_emails is not an attribute of Booth or User or BoothUser model.
And what I found on web are ways to pass arguments using strong parameters(?) to permit an attribute of a model using form_for or ajax. But no one seems to have passed input that is not an attribute of a model to the controller.
So, I wanted to ask is there a way to do so and if there is, how do I do it? Or is it just not allowed?

You should be able to create it like this:
BoothUser.create(user: current_user, booth: #booth, is_admin: true) #add current user
booth_admins.each do |email|
admin = User.find_by(email: email)
BoothUser.create(user: admin, booth: #booth, is_admin: true)
end
In your HTML, you need to create your textarea like this:
<textarea id="create_booth_admins_textarea" name="booth[booth_admin_emails]" rows="30" cols="50"> </textarea>
Then you don't need the JavaScript at all.
...however if you want the entire form to submit via AJAX, then in addition to the HTML changes above, in your JavaScript do this:
$('#booth_create_submit').click(function(e) {
e.preventDefault(); # keeps the HTML form from submitting.
var the_form = $(this.form);
$.ajax({
url: the_form.attr('action'),
data: the_form.serialize(),
type: "post",
cache: false,
success: function () {
console.log("ajax successful");
alert("ajax successful");
},
error: fucntion() {
console.log("ajax error");
alert("ajax error")
}
});
});

Related

Alternative ways to display available rooms in drop-down menu?

For some time now, I'm trying to generate a reservation form, where only available rooms are listed for the arrival and departure dates chosen in that same reservation form. Unfortunately, until now I didn't manage to do so.
I set out a question already on my previous attempt, without any success. => https://stackoverflow.com/posts/59083421/edit
I'm now trying to look for alternative ways to get there. For reference, please find my previous attempt below.
Previous attempt: general idea
Tried to send/receive an AJAX. Cannot reach the success stage, and the bug seem lie in the dataType the AJAX call is expecting/I'm sending (JS vs JSON). Unfortunately, I don't know how to solve this.
When I use format.js in my controller, I do not reach the success stage in my ajax call
when I use render json: {:rooms => #rooms} I do not reach my hotels/rooms_availability.js.erb file and subsequently am not able to insert my available rooms.
Previous attempt: code
reservations/new.html.erb
<%= simple_form_for [#hotel, #reservation] do |f|%>
<div class="col col-sm-3">
<%= f.input :arrival,
as: :string,
label:false,
placeholder: "From",
wrapper_html: { class: "inline_field_wrapper" },
input_html:{ id: "start_date"} %>
</div>
<div class="col col-sm-3">
<%= f.input :departure,
as: :string,
label:false,
placeholder: "From",
wrapper_html: { class: "inline_field_wrapper" },
input_html:{ id: "end_date"} %>
</div>
<div class="col col-sm-4">
<%= f.input :room_id, collection: #rooms %>
</div>
<%= f.button :submit, "Search", class: "create-reservation-btn"%>
<% end %>
script for reservations/new.html.erb
<script>
const checkIn = document.querySelector('#start_date');
const checkOut = document.querySelector('#end_date');
const checkInAndOut = [checkIn, checkOut];
checkInAndOut.forEach((item) => {
item.addEventListener('change', (event) => {
if ((checkIn.value.length > 0) && (checkOut.value.length > 0)){
checkAvailability();
}
})
})
function checkAvailability(){
$.ajax({
url: "<%= rooms_availability_hotel_path(#hotel) %>" ,
dataType: 'json',
type: "POST",
data: `arrival=${start_date.value}&departure=${end_date.value}`,
success: function(data) {
console.log('succes')
console.log(data);
},
error: function(response) {
console.log('failure')
console.log(response);
}
});
};
</script>
hotels_controller
def rooms_availability
hotel = Hotel.includes(:rooms).find(params[:id])
arrival = Date.parse room_params[:arrival]
departure = Date.parse room_params[:departure]
time_span = arrival..departure
#unavailable_rooms = Room.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival <= ? AND ? >= reservations.departure", arrival, departure).distinct
#hotel_cats = hotel.room_categories
#hotel_rooms = Room.where(room_category: hotel_cats)
#rooms = hotel_rooms - #unavailable_rooms
render json: {:rooms => #rooms}
#respond_to do |format|
#format.js
#end
end
def room_params
params.permit(:arrival, :departure, :format, :id)
end
hotels/rooms_availability.js.erb
var selectList = document.getElementById('reservation_room_id')
function empty() {
selectList.innerHTML = "";
}
empty();
<% unless #rooms.empty? %>
<% #rooms.each do |room|%>
selectList.insertAdjacentHTML('beforeend', '<option value="<%= room.id %>"><%= room.name %></option>');
<% end %>
<% end %>

How to automatically validate coupon and adjust price?

I'm trying to add a coupon to my checkout page, using an AJAX request that validates the coupon and updates the price accordingly. However, on loading the checkout view I get the error message:
First argument in form cannot contain nil or be empty
referring to the line <%= form_for #actioncode, method: :post ... in the form where the coupon is entered. I've tried to follow the steps here. How should I adjust my code?
The set up: #actioncode refers to a model where the admin stores actioncodes. Coupon_code is not included in any model but refers to the value that a user enters in the form. Coupon_code should be checked against the Actioncode model (specifically the 'actioncode' column) if the value exists (validation) and if so update the price based on the value in the Actioncode model in the colum 'discount'.
The checkout view contains the following form:
<%= form_for #actioncode, method: :post, url: {action: "check_actioncode"}, remote: true do |f| %>
<%= f.text_field :coupon_code, :placeholder => "Enter your coupon" %>
<%= f.submit "Submit Coupon Code" %>
<% end %>
Routes:
post 'check_actioncode' => 'actioncodes#check_actioncode'
In the actioncodes controller I have:
def check_actioncode
#actioncode = Actioncode.find(params[:coupon_code])
respond_to do |format|
if !#actioncode.nil?
format.js {}
else
flash.now[:success] = "Action code not found or expired"
end
end
end
The organizations controller renders the checkout view:
def checkout
#organization = Organization.new(organizationnew_params)
if #organization.save
#organization.members.each do |single_member|
single_member.send_activation_email
end
#actioncode = Actioncode.new
#amount = 100.00
#currency = "EUR"
#description = #organization.id
#transaction_description = "My description"
#transaction_type = "S"
#hash = hash(#description, #amount, #currency, #transaction_type)
render 'checkout' # This renders the checkout view.
else
render 'new_premium'
end
end
Update: If I add #actioncode = Actioncode.new to the controller that loads the view, I get another error message undefined method 'coupon_code' referring to the 2nd line of the form. coupon_code is indeed a variable nowhere defined but it should simply be a temporary value that the user has entered and that is checked against the actioncode in the model for validation. How should I do this?
Change your form to:
<%= form_for #actioncode, method: :post, url: {action: "check_actioncode", :controller => 'actioncodes'}, remote: true do |f| %>
<%= f.text_field :actioncode, :placeholder => "Enter your coupon" %>
Change your controller to:
def check_actioncode
#actioncode = Actioncode.where(:actioncode => params[:actioncode][:actioncode]).first
respond_to do |format|
unless #actioncode.blank?
format.js {}
else
flash.now[:success] = "Action code not found or expired"
end
end
end

Ajax request in rails 4 to update value

I have a vote button, which simply displays the amount of votes and by clicking on it, a vote is automatically added. Now I would like to add an Ajax request, so that the page doesn't refresh. Unfortunately I have never used Ajax before and therefor have no idea how to use it with Rails. I tried going through a few tutorials, but nothing seems to help.
view:
<%= link_to vote_path(:the_id => Amplify.all.where(question_id: question.id)[0].id, :the_user_id => #current_user.id), :remote => true do %>
<button class="fn-col-2 fn-col-m-3 amplify">
<%= image_tag "logo-icon-white.png" %>
<p class="count"><%= Amplify.all.where(question_id: question.id)[0].users.count %></p>
</button>
<% end %>
controller:
def vote
#amplify = Amplify.find(params[:the_id])
#current_user = User.find(params[:the_user_id])
if #amplify.users.where(:id => #current_user.id).count != 0
#amplify.users.delete(#amplify.users.where(:id => #current_user.id).first)
else
#amplify.users << #current_user
end
#question = Question.where(id: #amplify.question_id)[0]
#amplify.update(:votes => #amplify.users.count)
#question.update_attributes(:votes => #amplify.votes)
redirect_to root_path
end
routes:
get '/vote' => "amplifies#vote", :as => "vote"
jQuery(document).ready(function($){
$('.amplify').on('click', function(){
var that = $(this);
$.ajax({
url: '/vote',
data: {id: 'your id'},
/**
* Response from your controller
*/
success: function(response) {
that.siblings('.count').first().text(response);
}
});
})
})
I like calling it like waldek does but with coffeescript.
However, in your example, you are using :remote => true which is the unobtrusive way
Basically you are then going into the controller where you will need a format.js
respond_to do |format|
format.html # if you are using html
format.js # this will call the .js.erb file
end
Then create a file vote.js.erb where you can then access your instance variables and write js
console.log('you are here');

RoR how to submit form with :remote=>true and then execute javascript code

I want to be able to submit a form remotely (so the page does not refresh) and then have some javascript code get executed. Here's what I got so far
<script>
$(function() {
// Subscribe to receive messages!
var client = new Faye.Client('http://localhost:9292/faye');
// Our own private channel
var private_subscription = client.subscribe('<%=request.path + #id1.to_s + #id2.to_s%>',
function(data) {
$('<p></p>').html(data.username + ": " + data.msg).appendTo('#chat_room');
});
// Handle form submission to publish messages.
$('#new_message').submit(function(){ // THIS LINE GIVING TROUBLE
client.publish('<%=request.path + #id1.to_s + #id2.to_s%>', {
username: '<%= #user.fname+' '+#user.lname%>',
msg: $('#message_message').val()
});
// Clear the message box
$('#message_message').val('');
return false;
});
});
</script>
<div class="chat_container">
<div id="chat_room">
<p>Chat with <%= #other.fname+' '+#other.lname%> </p>
</div>
<%= simple_form_for Message.new, :id => "new_message",:controller => "messages", :action => "create", :remote => true do |f| %>
<%= f.text_field :message, :autocomplete => "off" %>
<%= f.hidden_field :sender_id, :value => #user.user_id %>
<%= f.hidden_field :receiver, :value => #other.user_id %>
<%= f.hidden_field :sent_at, :value => Time.now %>
<%= f.submit "Send", class: "btn btn-medium btn-primary" %>
<% end %>
</div>
If I change the name of my javascript function "#new_message" to anything else, the form submits properly into my database, but I lose the chatroom functionality. (The code that transmits the message to all clients in that chat room, via FAYE, and clears the text_box will not get called.)
If I keep the name of my javascript function "#new_message", the message will get transmitted to all clients in the chatroom, and the textbox will get cleared, but nothing will get stored into my database.
What can I do so that I can accomplish both the data storage and the chatroom functionality?
EDIT:Attempted this to no avail
$('#new_message').bind('ajax:success', function() {
client.publish('<%=request.path + #id1.to_s + #id2.to_s%>', {
username: '<%= #user.fname+' '+#user.lname%>',
msg: $('#message_message').val()
});
// Clear the message box
$('#message_message').val('');
return false;
});
});
I think you just need to hook into one of the ajax callbacks for the form submit:
$("#new_message").bind("ajax:success", function(evt, data, status, xhr) {
// Your client code and message clearing code
});

dynamically displaying data in text field ruby on rails

Hello guys i am trying attempt a dynamic select here. as soon as i select the customer his total value in the bill should come and get displayed in the text field tag.
the view
jQuery(document).ready(function(){
jQuery(".customerid").bind("change", function() {
var data = {
customer_id: jQuery(".customerid :selected").val()
}
jQuery.ajax({
url: "get_cust_bill",
type: 'GET',
dataType: 'script',
data: data
});
});
});
</script>
<div class ="customerid"><%= f.label :customer_id %>
<%= f.collection_select :customer_id, Customer.all, :id, :name, options ={:prompt => "-Select a Customer"}, :class => "state", :style=>'width:210px;'%></div><br />
<div class ="customerbill">
<%= f.label :total_value, "Total Value" %>
<%= render :partial => "customerbill" %>
js.erb file
jQuery('.customerbill').html("<%= escape_javascript(render :partial => 'customerbill') %>");
the customerbill partial
<% options = []
options = #cust_bill.total_value if #cust_bill.present? %>
<%= text_field_tag "total_value", options %>
in contoller
def get_cust_bill
#cust_bill = CustomerBill.find_all_by_customer_id(params[:customer_id]) if params[:customer_id]
end
I feel the problem lies in the partial, the way i am calling the options so can anyone guide me how to get the value in text field??? thank in advance.
From what I understand, total_value text field does not show anything. Could you try to output the value of options and check if it always has a value? I suggest you check out the documentation for the text_field_tag. Basically, it accepts three variables like this:
text_field_tag(name, value = nil, options = {})
i was using getJSON method....and i feel that can be used here. hope the followng works.
jQuery(document).ready(function()
{
jQuery(".customerid select").bind("change", function() {
var data = {
product_id: jQuery(this).val()
}
jQuery.getJSON(
"/controller_name/get_cust_bill",
data,
function(data){
var result = "";
res = parseFloat(a[1]);
jQuery('.price input').val(res);
});
});
});
controller
def get_cust_bill
#cust_bill = CustomerBill.find_all_by_customer_id(params[:customer_id]).map{|p| [p.price]} if params[:customer_id]
respond_to do |format|
format.json { render json: #cust_bill }
end
end
so no need of calling js. erb partial you can simply have
<div class = "price"><%= f.input :price, :label => 'Price', :input_html => { :size => 20} %></div><br/>
all the best :)

Categories

Resources