I have product and order models. Product has many orders and order belongs to product. There is a button 'Order' on product's page, when a user clicks on it, a bootstrap modal opens up. On this modal I render order's form to create a new one.
I want to know, how to pass a product's id to this form on modal?
Currently my button to open modal look like this:
%button.btn.btn-info.btn-lg{"data-target" => "#myModal", "data-toggle" => "modal", :type => "button"} Order
And the modal itself:
#myModal.modal.fade{:role => "dialog"}
.modal-dialog
.modal-content
.modal-header
%button.close{"data-dismiss" => "modal", :type => "button"} ×
%h4.modal-title Order form
.modal-body
= render 'orders/form'
.modal-footer
%button.btn.btn-default{"data-dismiss" => "modal", :type => "button"} Close
I need this product's id to create a new order, which will belong to the product. If I think in wrong direction, please, correct me.
Many thanks in advance for help!
UPDATE Solved!! Many-many-many thanks to Arup Rakshit (#ArupRakshit)!!!
- #products.last(3).each do |product|
%h4= product.name
%button.btn.btn-info.btn-lg{"data-target" => "#myModal", "data-toggle" => "modal", :type => "button", data: {product_id: product.id}} Order
#myModal.modal.fade{:role => "dialog"}
.modal-dialog
.modal-content
.modal-header
%button.close{"data-dismiss" => "modal", :type => "button"} ×
%h4.modal-title Order Form
.modal-body
#new_order
= render 'orders/form', product: product
.modal-footer
%button.btn.btn-default{"data-dismiss" => "modal", :type => "button"} Close
orders/form:
= form_for Order.new do |f|
= f.hidden_field :product_id
= f.text_field :user_name, placeholder: 'Name', class: 'form-control'
= f.submit 'Order', class: 'btn btn-primary'
application.js:
$( document ).ready(function() {
$('body').on('shown.bs.modal', '#myModal', function (e) {
var product_id = $(e.relatedTarget).data('product-id');
$('#order_product_id').val(product_id);
});
});
Keep the product in the modal button using data attribute. Like
%button.btn.btn-info.btn-lg{"data-target" => "#myModal", "data-toggle" => "modal", :type => "button", data: {product_id: #product.id}} Order
Inside the form add the hidden field:
= form_for Order.new do |f|
.form-group
= f.text_field :user_name, placeholder: 'Name', class: 'form-control'
= f.hidden_field :product_id
You need to use below JS, to populate the hidden field value.
$('body').on('shown.bs.modal', '#myModal', function (e) {
var product_id = $(e.relatedTarget).data('product-id');
$('#order_product_id').val(product_id);
});
#new_order is the form ID, change it to yours one. Bootstrap modal events.
Related
I have a form with conditional bootstrap:
= simple_form_for(#user) do |f|
= f.input :first_name
- if f.object.new_record?
%button.btn.btn-primary{"data-target" => "#accordion", "data-toggle" => "collapse", :type => "button"}
.fa.fa-cog
More options
#accordion.collapse
= f.input :many_more_fields
- else
= f.input :many_more_fields
Is there a better way to make only the css conditional, in order not to have to duplicate = f.input :many_more_fields.
CSS part:
%button.btn.btn-primary{"data-target" => "#accordion", "data-toggle" => "collapse", :type => "button"}
.fa.fa-cog
More options
#accordion.collapse
P.S. Any ideas, except creating a partial for = f.input :many_more_fields?
i'm trying to load a payment form within a modal within a rails form. As it is right now, when I click "Buy Now" the modal will load, but the form will submit. How do I have it not submit until, the someone clicks "Submit" in the modal.
= form_tag foo_path, id: 'payment-form' do
-if #store.products == nil
Test
- #store.products.each_with_index do |product, index|
.row
.col-lg-2
- if current_user
- if store.user_id == current_user.id
= link_to "Delete", product_path(product), data: { method: "delete", confirm: "Are you sure?"}
.col-lg-8
.panel.panel-default
.panel-body
.row
.col-lg-2
%input{:type => "checkbox", :id => "switchName#{index}", :class => "check"}/
%label{:for => "switchName#{index}"}
.col-lg-8
= hidden_field_tag("order_products[][product_id]", product.id)
= product.name
%br
.subheader= number_to_currency(product.cost_in_cents.to_f / 100)
.col-lg-2
= select_tag("order_products[][quanity]", options_for_select([0,1,2,3,4,5,7,8,9,10,11,12,13,14,15]), "data-cost-per-unit" => product.cost_in_cents, id: product.name, class: "drop", :prodindex => index)
.col-lg-2
-if current_user
-else
%span.payment-errors
.text-center
%h2.total-amount
Total:
$0.00
%hr
.text-center
%button.btn.btn-primary.btn-lg{"data-target" => "#myModal", "data-toggle" => "modal"}
Buy Now
By default, when clicking on a <button> element, the containing form is submitted: source.
If you use {"data-target" => "#myModal", "data-toggle" => "modal", "type" => "button"} when creating your button, it should display your modal without submitting the form.
Then, you'll have to handle submitting the form in your modal if that's what you want to happen.
I have a form that updates an #identity object. Two #identity attributes need to be assigned from a separate collection #accounts.
#accounts = [{
'name' => 'A',
'page_id' => 1},
{
'name' => 'B',
'page_id' => 2
}]
The form needs display the name, but pass both the name and page_id.
<%= simple_form_for(#identity, :remote => true) do |f| %>
<%= f.input :page_name, :collection => #accounts.map { |a| a['name'] }, :as => :radio_buttons, :item_wrapper_tag => :li %>
<%= f.submit 'Submit', :class => 'btn btn-primary' %>
<% end %>
How can I also pass the matching page_id attribute without displaying it?
:collection => #accounts.map { |e| [e['name'], e['page_id']] }
I have a form like so:
.row-fluid
= form_for(#client) do |f|
- if #client.errors.any?
#error_explanation
%h2
= pluralize(#client.errors.count, "error")
prohibited this client from being saved:
%ul
- #client.errors.full_messages.each do |msg|
%li= msg
.fieldset
%legend
= #header
.control-group
%label.control-label
Name
.controls
= f.text_field :name, :class => "input-xlarge"
.control-group
%label.control-label
Street Address
.controls
= f.text_field :street, :class => "input-xlarge"
.control-group
%label.control-label
Unit
.controls
= f.text_field :unit, :class => "input-small", :placeholder => "optional"
.control-group
%label.control-label
City
.controls
= f.text_field :city, :class => "input-xlarge"
.control-group
%label.control-label
State
.controls
= f.text_field :state, :class => "input-small"
.control-group
%label.control-label
Zip
.controls
= f.text_field :zip, :class => "input-small"
.form-actions
= f.submit "Save", :class => "btn btn-primary"
.btn
= link_to "Cancel", :root, :style => "color: #333; text-decoration: none;"
and I have a modal i'm loading up with the form inside like so:
.span2.offset2
%a.btn{"data-toggle" => "modal", :href => "#myModal", :role => "button"} New Client
/ Modal
#myModal.modal.hide.fade{"aria-hidden" => "true", "aria-labelledby" => "myModalLabel", :role => "dialog", :tabindex => "-1"}
.modal-header
%button.close{"aria-hidden" => "true", "data-dismiss" => "modal", :type => "button"} ×
%h3#myModalLabel Modal header
.modal-body
%p
= render "form"
.modal-footer
%button.btn{"aria-hidden" => "true", "data-dismiss" => "modal"} Close
%button.btn.btn-primary Save changes
I'm wondering how to get the Save Changes button to submit the form. Do I need to add javascript to get it to work?
You need to make sure that the inputs and the buttons belong to one form element. This may be hard to achieve with your current markup.
Alternatively, you could submit the form with JavaScript, but the first method is much better, as you get a lot of functionality for free.
I'm trying to follow this post How can I unobtrusively disable submit buttons with Javascript and Prototype? but I can't get it to work. The form triggers an RJS function, so I need to keep the helpers' onclick events intact. The RJS returns/reloads the same forms along with two new texts. I'm really confused. Here is my rails code for the forms:
.span-20#comparison
/ new comparison . . .
/ voting forms (also reloaded)
.span-4.prepend-3.append-6
- form_remote_tag :action => url_for(:controller => :comparisons), :method => :post do
= hidden_field_tag :poem1_id, poems[:a].id
= hidden_field_tag :poem2_id, poems[:b].id
= hidden_field_tag :response, 1
= submit_tag "Vote for me", :disabled => false, :disable_with => 'Vote for me', :class => "compare"
.span-4.append-3.last
- form_remote_tag :action => url_for(:controller => :comparisons), :method => :post do
= hidden_field_tag :poem1_id, poems[:a].id
= hidden_field_tag :poem2_id, poems[:b].id
= hidden_field_tag :response, 2
= submit_tag "Vote for me", :disable_with => 'Vote for me', :class => "compare"
.span-4.prepend-8.append-8.prepend-top.last
- form_remote_tag :action => url_for(:controller => :comparisons), :method => :post do
= hidden_field_tag :poem1_id, poems[:a].id
= hidden_field_tag :poem2_id, poems[:b].id
= hidden_field_tag :response, 'draw'
= submit_tag "Declare Draw", :disable_with => 'Declare Draw', :class => "compare"
RJS
page.replace_html :comparison, :partial => 'poems', :object => #poems
page.insert_html :top, :previous, :partial => 'comparison', :object => #comparison
page << "Effect.ScrollTo($('top'));"
Here's one way you could do it using Prototype:
<script type="text/javascript">
document.observe("dom:loaded" function() {
$$("input .compare").each(function(submit) {
submit.observe("click", function() {
submit = true;
});
});
});
</script>
This adds an onclick event handler to every input element with a compare CSS class (i.e. your submit buttons) when the DOM is loaded. The onclick event handlers disables each button when it's clicked. Note that adding event handlers using Prototype this way does not replace any existing event handlers on the elements.