Rails 4: passing custom data and form data in ajax call - ruby-on-rails

I am trying to submit a simple form using ajax call this way
$('#save-artificial-form').click(function () {
var fd = $('#categories-form').serialize();
console.log(fd);
var url = "/categories";
$.ajax({
type: 'POST',
url: url,
data: $('#categories-form').serialize(),
success: function() {
return true;
}
});
It works perfectly fine and save form data. But I want to add one more data category_type but I don't know how to do this. I want something like this
data: $('#categories-form').serialize(), category_type: "advanced"
How can I do this? It is okay if category_type is added/pushed in the fd variable above.
code in my form
<%= form_for(#category, :html => {:id => "categories-form", class: "form-alt"}) do |f| %>
<% if #category.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#category.errors.count, "error") %> prohibited this category from being saved:</h2>
<ul>
<% #category.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :enabled %><br>
<%= f.check_box :enabled %>
</div>
<div style="margin: 6px 0px 0 0 !important;">
<%= link_to "This is test", 'javascript:void(0)', id: "save-artificial-form", :rel => "tooltip", :title => "save" %>
</div>
<% end %>

Option 1:
Use a hidden field and it will be added automatically to the serialized string
<%= f.hidden_field :category_type, value: 'advanced' %>
Option 2:
Concat the missing value to the serialized string ie. "param=value"+ "&missing_data=bar"
data: $('#categories-form').serialize() + '&category_type=advanced'

Related

Displaying different divs based on dropdown selection in Rails form

I am trying to create a form in Rails that includes a dropdown menu with three options: 'foo', 'bar', and 'baz'. If the user selects one of these options, I want to display a different div based on the selected option.
Here is my code:
<% options = [['Foo', 'foo'], ['Bar', 'bar'], ['Baz', 'baz']] %>
<%= form.label :type %>
<%= form.select :type, options_for_select(options, #selected_type), name: 'type' %>
<% if #selected_type == 'foo' %>
<div>
<%= form.hidden_field :type, value:'foo' %>
</div>
<% elsif #selected_type == 'bar' %>
<div>
<%= form.hidden_field :type, value:'bar' %>
</div>
<% elsif #selected_type == 'baz' %>
<div>
<%= form.hidden_field :type, value:'baz' %>
</div>
<% end %>
This is in my controller:
#vendor_item = VendorItem.new
#selected_type = params[:type]
puts "Selected type: #{#selected_type}"
I have implemented this using a select element, but the form is not working as expected. When I select an option from the dropdown menu, the form is not being submitted, and the divs are not being displayed.
CASE 1: If the form should be submitted on the server side, after the dropdown change:
<% options = [['Foo', 'foo'], ['Bar', 'bar'], ['Baz', 'baz']] %>
<%= form_with url: "your URL goes here", class: 'test_submit_form' do |form| %>
<%= form.label :type %>
<%= form.select :type, options_for_select(options, #selected_type), name: 'type' %>
<% if #selected_type == 'foo' %>
<div>
<%= form.hidden_field :type, value:'foo' %>
</div>
<% elsif #selected_type == 'bar' %>
<div>
<%= form.hidden_field :type, value:'bar' %>
</div>
<% elsif #selected_type == 'baz' %>
<div>
<%= form.hidden_field :type, value:'baz' %>
</div>
<% end %>
<%= form.submit %>
<% end %>
Javascript:
<script>
$('#type').on('change', function(){
$('form.test_submit_form').submit();
});
</script>
CASE 2: If you just need to show/hide DIVs on client side, after dropdown change:
<% options = [['Foo', 'foo'], ['Bar', 'bar'], ['Baz', 'baz']] %>
<%= form_with url: "your URL goes here", class: 'test_submit_form' do |form| %>
<%= form.label :type %>
<%= form.select :type, options_for_select(options, #selected_type), name: 'type' %>
<div class="option-container foo" style="display: <%= #selected_type == 'foo' ? 'block' : 'none'%>">
<%= form.hidden_field :type, value:'foo' %>
</div>
<div class="option-container bar" style="display: <%= #selected_type == 'bar' ? 'block' : 'none'%>">
<%= form.hidden_field :type, value:'bar' %>
</div>
<div class="option-container baz" style="display: <%= #selected_type == 'baz' ? 'block' : 'none'%>">
<%= form.hidden_field :type, value:'baz' %>
</div>
<%= form.submit %>
<% end %>
Javascript:
<script>
$('#type').on('change', function(){
$('.option-container').hide();
$('.option-container.' + $(this).val()).show();
});
</script>
Notice the option-container and option (foo, bar, baz) class on div and controller code will remain the same for both cases:
#selected_type = params[:type]

New search form partial is redirecting to my main index page for the model

I have an events model and I have an address field where I have some geolocation logic being implemented. On my main index page, I'm rendering a search form partial that works just fine to be all to search all of the events in my database.
Here's the original search form:
<%= search_form_for #q,
data: { controller: "places", action: "google-maps-callback#window->places#initMap" } do |f| %>
<div class="formlook">
<div class="event-search-container">
<div class="event-name">
<%= f.label "Event name", class: "form-label" %>
<%= f.search_field :name_cont, placeholder: "Any event", class: "form-control" %>
</div>
<div class="geolocation">
<%= f.label "Geolocation", class: "form-label" %>
<%= f.search_field :address_or_city_or_state_or_country_or_continent_cont_all, class: "form-control", placeholder: "Search by continent, country, state, or city", data: { places_target: "field" } %>
</div>
<div class="dancestyle">
<%= f.label "Dance style", class: "form-label" %>
<%= f.select(:dance_styles_id_in, DanceStyle.all.pluck(:name, :id), { :include_blank => "All dance styles" }, { class: "form-select", id: "select-dancestyle", multiple: true, placeholder: "Any dance style" }) %>
</div>
<div class="eventtype">
<%= f.label "Event Type", class: "form-label" %>
<%= f.select :event_type_id_in, EventType.all.pluck(:name, :id), { :include_blank => "All event types" }, { id: "select-artist", multiple: true, placeholder: "Any event type", class: "form-select" } %>
</div>
<div class="month">
<%= f.label "Month", class: "form-label" %>
<%= f.select(:event_month_in, (Date::MONTHNAMES[1..12]), { prompt: "Any month" }, { id: "select-month", :include_blank => "Any month", class: "form-select", multiple: true }) %>
</div>
<div class="year">
<%= f.label "Year", class: "form-label" %>
<%= f.select :event_year_in, Date.today.year-2 .. Date.today.year+3, { prompt: "Any year" }, { id: "select-year", include_blank: true, class: "form-select", multiple: true } %>
<br>
</div>
</div>
</div>
<%= f.submit "Search!", class: "button-orange" %>
<% end %>
I'm now creating specific event index pages for particular cities now. So I want to be able to use the other search parameters from my main index page without the name or the address field. So I created a new html erb file with a new scope based off the event model for a particular city:
<div class="container index">
<div>
<h1>Dance Events in Austin, Texas!</h1>
<br>
<div class="help-attn">
<p>All of the search options work together! Create your own search filters to find the events you want!</p>
</div>
<%= render 'events/local_search_form' %>
<br>
<h5>Currently displaying <%= pluralize(#events.in_austin.count, "event") %>. </h5>
<br>
</div>
<h3>Upcoming Events</h3>
<div class="event-list-wrapper">
<% #events.upcoming_events.in_austin.each do |event| %>
<%= render 'event', event: event %>
<% end %>
</div>
<h3>Past Events</h3>
<div class="event-list-wrapper past-event">
<% #events.past_events.in_austin.each do |event| %>
<%= render 'event', event: event %>
<% end %>
</div>
I also needed to add the def atx_index to my event model with the same parameters as the def index since in my head they are both index pages, just one has a different scope.
From above you will see that I created a different search form partial to reflect the two fields I don't need anymore, here's the new search form partial.
<%= search_form_for #q do |f| %>
<div class="formlook">
<div class="local-search-container">
z <%= f.hidden_field :address_or_city_or_state_or_country_or_continent_cont_all, value: [""] %>
<div class="dancestyle">
<%= f.label "Dance style", class: "form-label" %>
<%= f.select(:dance_styles_id_in, DanceStyle.all.pluck(:name, :id), { :include_blank => "All dance styles" }, { class: "form-select", id: "select-dancestyle", multiple: true, placeholder: "Any dance style" }) %>
</div>
<div class="eventtype">
<%= f.label "Event Type", class: "form-label" %>
<%= f.select :event_type_id_in, EventType.all.pluck(:name, :id), { :include_blank => "All event types" }, { id: "select-artist", multiple: true, placeholder: "Any event type", class: "form-select" } %>
</div>
<div class="month">
<%= f.label "Month", class: "form-label" %>
<%= f.select(:event_month_in, (Date::MONTHNAMES[1..12]), { prompt: "Any month" }, { id: "select-month", :include_blank => "Any month", class: "form-select", multiple: true }) %>
</div>
<div class="year">
<%= f.label "Year", class: "form-label" %>
<%= f.select :event_year_in, Date.today.year-2 .. Date.today.year+3, { prompt: "Any year" }, { id: "select-year", include_blank: true, class: "form-select", multiple: true } %>
<br>
</div>
</div>
</div>
<%= f.submit "Search!", class: "button-orange" %>
<% end %>
So the specific city event index page is displaying properly following the scope but when I use the search I'm redirected to the main event index page with the search parameters that I inputted. I'm not understanding how the two different search form partials are both linked to the main event index page.
How do I get the new search form partial for the specific city index page to display the search results on its corresponding page?
The issue to my redirect form issue was that I need to set the URL of the new form I created, so I was able to get the proper path names from the routes.
My initial implementation though had my configuring the form specifically and since I wanted to reuse the form on multiple pages for the individual local cities, I was lucky to find an old 7 year old SOF article that referred to setting the url in the render line like this:
<%= render 'events/local_search_form', { url: atx_index_path } %>
and then calling that url string in the local_search_form like so:
<% if local_assigns.has_key? :url %>
<%= search_form_for #q, { url: url } do |f| %>
and now I can simply change the url path for each html.erb file I create for each individual city! I didn’t know about the local assigns!

nested <div> element inside <button> element to get both links working

Open image here
So here's the situation I am trying to nest a div element ( a paypal button ) and a button element (rails element which submits forms) so on clicking, form gets submitted after paypal successful transaction.currently only one of it works No IDEA ON How to also redirect to a paypal payments page.### Please tell me any other way.if I'm following a wrong path ###. Here's the code
<%= form_for([#listing, #order]) do |form| %>
<% if order.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(order.errors.count, "error") %> prohibited this order from being saved:</h2>
<ul>
<% order.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= form.label :name %>
<%= form.text_field :name, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :size %>
<%= form.text_field :size, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :mobile %>
<%= form.text_field :mobile, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :city %>
<%= form.text_field :city, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :address %>
<%= form.text_field :address, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :PinCode %>
<%= form.text_field :PinCode, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :Landmark %>
<%= form.text_field :Landmark, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :Description %>(if any special changes)
<%= form.text_field :Description, class:"form-control" %>
</div>
<div class="form-group">
<%=form.submit%>
<%=link_to "Checkout" %>
</div>
<button type="submit" onClick="placeOrder(this.form)" class="button button2">
<!-- Set up a container element for the button -->
<div id="paypal-button-container"> </div>
<!-- Include the PayPal JavaScript SDK -->
<script src="https://www.paypal.com/sdk/js?client-id=sb&currency=USD"></script>
<script>
// Render the PayPal button into #paypal-button-container
paypal.Buttons({
// Set up the transaction
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: '0.01'
}
}]
});
},
// Finalize the transaction
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
// Show a success message to the buyer
alert('Transaction completed by ' + details.payer.name.given_name + '!');
});
}
}).render('#paypal-button-container');
</script>
<%=form.submit%>
Place Order</button>
If the form submission depends on the paypal transaction success, then submit the form only ater the transaction was approved on the onApprove callback. Something like this:
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
// Show a success message to the buyer
alert('Transaction completed by ' + details.payer.name.given_name + '!');
yourForm = document.getElementById('id_of_the_form');
Rails.fire(yourForm, 'submit');
});
}

Rails - Search results are not filtered. Returning all availability

The task scope: A user selects an option from a drop down menu (Single/Double bedroom), clicks on search button and gets all related results. Then on the search page the user can further refine results by using available filters (TV/Shower). For some reason none of these actions modify the search results- the page displays all available listings in the database, rather than the ones that match the criteria..
What am I doing wrong?
Here is what I have so far:
HOME SEARCH BAR
<%= form_tag search_path, method: :get do %>
<div class="row">
<div class="col-md-7">
<%= select_tag :bedroom, options_for_select([['Single', 1], ['Double', 2]]), class: "form-control" %>
</div>
<div class="col-md-2">
<%= submit_tag "Search", class: "btn btn-normal btn-block" %>
</div>
</div>
<% end %>
SEARCH PAGE
<div class="col-sm-3">
<%= search_form_for #search, url: search_path, remote: true do |f| %>
<div class="row">
<div>
<%= check_box_tag "q[is_tv_eq]", true %> TV
</div>
<div>
<%= check_box_tag "q[is_shower_eq]", true %> Shower
</div>
</div>
<div class="row text-center">
<%= f.submit "Search", class: "btn btn-form" %>
</div>
<% end %>
<%= render partial: "rooms/rooms_list", locals: {rooms: #arrRooms} %>
</div>
ROOM LIST PARTIAL
<% rooms.each do |room| %>
<div class="row">
<%= image_tag room.cover_photo(:medium) %>
<%= link_to room.user_id, room %>
<%= room.price %> - <%= room.bedroom %>
<div id="star_<%= room.id %>"></div> <%= pluralize(room.average_rating, "review") %>
</div>
<script>
$('#star_<%= room.id %>').raty({
path: '/assets',
readOnly: true,
score: <%= room.average_rating %>
});
</script>
<% end %>
ROOM MODULE
class CreateRooms < ActiveRecord::Migration[5.0]
def change
create_table :rooms do |t|
t.string :bedroom
t.integer :price
t.boolean :active
t.timestamps
end
end
end
PAGE CONTROLLER
def search
# STEP 1
if params[:search].present? && params[:search].strip != ""
session[:loc_search] = params[:search]
end
# STEP 2
if session[:loc_search] && session[:loc_search] != ""
#rooms_bedroom = Room.where(active: true, bedroom: session[:loc_search]).order(:price)
else
#rooms_bedroom = Room.where(active: true).all
end
# STEP 3
#search = #rooms_bedroom.ransack(params[:q])
#rooms = #search.result
#arRoooms = #rooms.to_a
end
DEFINED THE BEDROOM OPTIONS IN THE ROOM OVERVIEW PAGE (not sure if that helps)
<%= form_for #room do |f| %>
<div class="form-group">
<label> Bedroom Type </label>
<%= f.select :bedroom, [["Single", "Single"], ["Double", "Double"]],
id: "bedroom", prompt: "Select...", class: "form-control" %>
</div>
</div>
<div><%= f.submit "Save", class: "btn btn-normal" %></div>
<% end %>
Thanks

show rest of a form if a checkbox is ckecked in ruby on rails

I need to ask to my user if will pay a service with credit card...if it checked the option pay_with_card? it must show the rest of the form, that ask for other data like card number, mail, etc. if the user don't checked it, it must show a message, the question is...how can I do this? thanks in advance
<%= form_for(#product) do |f| %>
<%= f.label :pay_with_card? %>
<%= f.check_box :pay_with_card,{}, "Yes", "No"%>
<div>
<%= f.label :card_number %> <%= f.text_field :card_number %>
</div>
<div>
<%= f.label :mail %> <%= f.text_field :mail %>
</div>
<% end %>
Make the card number/mail details div style="display:none;", then add some javascript to the checkbox to change it to display:block;
Something like this:
<%= form_for(#product) do |f| %>
<%= f.label :pay_with_card? %>
<%= f.check_box :pay_with_card,{}, "Yes", "No"%>
<div id="card_details" style="display:none;">
<%= f.label :card_number %> <%= f.text_field :card_number %>
<%= f.label :mail %> <%= f.text_field :mail %>
</div>
<% end %>
<script type="text/javascript">
var checkbox = document.getElementById('product_pay_with_card');
var details_div = document.getElementById('card_details');
checkbox.onchange = function() {
if(this.checked) {
details_div.style['display'] = 'block';
} else {
details_div.style['display'] = 'none';
}
};
</script>
How about using jQuery?
First, wrap your credit card fields in a div with class credit_card_fields and than add this JS code to your page:
$("input[type='checkbox']#pay_with_card").on('change', function(){
$('.credit_card_fields').toggle();
});
You can use JS for it or move pay_with_card out of form like:
<%= link_to 'pay with card', your_current_path(:pay_with_card => 1) %>
<%= form_for(...) do |f| %>
<% if params[:pay_with_card] %>
<%= # fields for card %>
<% end %>
<% end %>
You can do it through jQuery, for example:
$ ->
$('select#pay_with_card').change ->
if $(this).val() == 'yes'
$('.card_block').slideDown('fast')
else
$('.card_block').slideUp('fast')
assumed that part of the form with payment card is included in the div with .card_block class
Ok my solution is this: all the code in the view, if a user check pay_with_card...(mi code is in spanish) it shows the complete form...if is not checked don´t show nothing, just the same checkbox asking for payment... thanks guys.
function mostrar (){
var checkbox = document.getElementById('chk_tarjeta');
if (checkbox.checked)
document.getElementById("card_details").style.display = "block";
else
document.getElementById("card_details").style.display = "none";
</script>
<h1>Forma de Pago</h1>
<%= form_for(#product) do |f| %>
<div id="product_pay_with_card">
<div >
<%= f.label :paga_con_tarjeta? %></br>
<%= f.check_box :paga_con_tarjeta, :id => "chk_tarjeta", :onclick => "mostrar();" %>
<div>
</div>
</div>
<div id="card_details" >
<div>
<%= f.label :numero_de_tarjeta %></br>
<%= f.text_field :numerotarjeta %>
</div>
<div>
<%= f.label :codigo_de_seguridad %></br>
<%= f.text_field :codigoseguridad %>
</div>
This worked for me with a form_with model and bootstrap
Change my_hidden_form with an id that makes sense for your form.
Original code is haml
= form_with scope: :model, url: models_path, local: true do |form|
.row
.col-6
.form-group
%h5.mb0 THE CASE TO TICK
= form.check_box :form_value, {:data => {:aria => {controls: :my_hidden_form, expanded: false}, :toggle => "collapse", :type => "checkbox", :target => "#my_hidden_form" }}
.row
.col-6
.form-group.collapse#my_hidden_form
%h5.mb0 THE FORM TO SHOW WHEN CASE IS TICKED
= form.text_field :name, placeholder: "A name"
.row
.col-md-12.text-right
= form.submit 'Submit', class: "btn btn-primary"
Converted to erb/html with https://haml2erb.org/
<%= form_with scope: :model, url: models_path, local: true do |form| %>
<div class="row">
<div class="col-6">
<div class="form-group">
<h5 class="mb0">THE CASE TO TICK
<%= form.check_box :form_value, {:data => {:aria => {controls: :my_hidden_form, expanded: false}, :toggle => "collapse", :type => "checkbox", :target => "#my_hidden_form" }} %>
</h5>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-group collapse" id="my_hidden_form">
<h5 class="mb0">THE FORM TO SHOW WHEN CASE IS TICKED
<%= form.text_field :name, placeholder: "A name" %>
</h5>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 text-right">
<%= form.submit 'Submit', class: "btn btn-primary" %>
</div>
</div>
<% end %>
Since the approach suggested by #Unixmonkey didn't work for me, here's a slight variation I put together using an event listener.
<script type="text/javascript">
const checkbox = document.getElementById('product_pay_with_card');
const details_div = document.getElementById('card_details');
checkbox.addEventListener("change", (event) => {
if (event.currentTarget.checked) {
details_div.style['display'] = 'block';
}
else {
details_div.style['display'] = 'none';
}
});
</script>

Resources