Data collection for filling the order is going to table with 3 pages (go to each at the touch of a button). Stored in the database they need only after you press the last button. How to store data from the first to the last page?
1 page
`<%= form_for(#orders) do |f| %>
<%= f.text_field :city,placeholder: "Город"%>
<%= f.submit "Далее", class: "btn" %>
<% end %>`
2 page
`<%= form_for(#orders) do |f| %>
<%= f.text_field :time, placeholder: "Время" %>
<%= f.submit "Далее", class: "btn" %>
<% end %>`
3 page
`<%= form_for(#orders) do |f| %>
<%= f.text_field :count, placeholder: "Количество" %>
<%= f.text_field :phone,placeholder: "Телефон для связи"%>
<%= f.submit "Заказать", class: "btn" %>
<% end %>`
While you could use the session or some other alternative storage mechanism actually saving the order in the database in the first step and performing the following steps as atomic update operations might be a much better solution.
The advantages are less complex logic and being able to avoid tricky chicken vs egg situations like for example how to route to a resource that does not have an id.
class Order < ActiveRecord::Base
enum status: [:draft, :confirmed, :processed, :shipped] # etc...
end
In this example you would use a bitmask column on the database - it should be set to zero by default an in the last step you would change the state of the order from draft to confirmed.
There are several gems such as wicked that are used to create wizards (step by step forms).
Yet another alternative is to use javascript to split a complex form into steps in the form of tabs or "slides" while the backend still processes it as a single operation.
Related
How would I go about creating a form that takes what user input as a value and just passes it to the controller without being connected to any model?
Something simple like i.e. calculating tax based on input salary, or other calculation like that, when I show the user a form, let them fill it, and when submitting it would go to the results
<%= form_with url: 'calculator#result' do |form| %>
<%= form.number_field :value, in: 1000.0..20000.0, step: 0.5 %>
<%= form.submit %>
<% end %>
i expected something like this to pass 'value' and redirect to calculator#result when submitting, but the button doesn't really do anything. whereas a form connected to a model seems pretty smart and does it
The form_tag Helper method is usually used for forms that are not linked to a model.
I think this should work:
<%= form_tag("/calculator/result", :method => "get") do %>
<%= label_tag(:value, "Value:") %>
<%= text_field_tag(:value) %>
<%= submit_tag("Submit") %>
<% end %>
Tried to figure this out for a while without being able to crack the nut.
What I am trying to do is this.
I have a user model, it has_many answers. I would like to restrict the ability for one user to answer the same answer more than once. I've been able to block this in the model, however not in the view.
I would like the submit button to see if the current_user.id is present in the current answer id (the one it's thinking about filling out), if so disable the submit button saying "already applied".
My answers#new
<%= form_for #answer do |f| %>
<%= f.hidden_field :application_id, value: #application.id %>
<% if #application.question_2.length && #application.question_3.length >= 1 %>
<p>Question 1: <%= #application.question_1 %></p>
<%= f.text_area :answer_1 %><br/>
<p>Question 2: <%= #application.question_2 %></p>
<%= f.text_area :answer_2 %><br/>
<p>Question 3: <%= #application.question_3 %></p>
<%= f.text_area :answer_3 %>
<% elsif #application.question_2.length >= 1 %>
<p>Question 1: <%= #application.question_1 %></p>
<%= f.text_area :answer_1 %><br/>
<p>Question 2: <%= #application.question_2 %></p>
<%= f.text_area :answer_2 %><br/>
<% else %>
<p>Question 1: <%= #application.question_1 %></p>
<%= f.text_area :answer_1 %><br/>
<% end %>
<%= f.submit "Submit answers", data: { disable_with: "Please wait..." } %>
<% end %>
I see a couple different pieces of this. When I write similar functionality, I think about the following questions:
What should happen on page load / reload?
Should anything happen without page reload (ie. via AJAX / JS)?
Should the action be disabled server-side, client-side, or both?
First of all, if the user has already submitted an answer by the time the page loads, the template should display the button differently. Usually it makes sense to not display a form at all in that case, but if you want the form with the button disabled, the following code comes to mind (see html example):
<% if #user_has_answered %>
<%= f.submit "Submit answers", disabled: true %>
<% else %>
<%= ... normal button ... %>
<% end %>
If you're concerned about preventing the user from clicking the button twice when they submit the form from the page, some simple Jquery can easily handle that, or you can use disable_with as in your example twice. This has nothing to do with the state of the database; it merely sets up a Javascript listener that disables the button as soon as it's clicked (and changes its text) to prevent the user from accidentally double-submitting when pages load slowly.
You mentioned that you have prevented double answers in the model. How does the controller handle this? If a user somehow manages to fill out the form a second time and submit it (perhaps Javascript is disabled and they had multiple tabs open on the same page? If it's possible, users do it), what do you want to happen to the data they've submitted? Show them a rejection message? Preserve their data on the same page? This functionality should be 80% automatic in Rails, if you want it, as long as you handle the request and rejection in the same way that form validation errors are handled.
I'm happy to be more specific if you share more detail about what you're looking for or having trouble with.
Assuming that Answer belongs_to Application, you could do...
<% if current_user.answers.collect(&:application).include?(#application) %>
<%= f.submit "already applied", disabled: true %>
<% else %>
<%= f.submit "Submit answers", data: { disable_with: "Please wait..." } %>
<% end %>
What I have now gives me a dropdown menu where I can only select one:
<%= form_for(#submission) do |f| %>
<%= f.collection_select :id, Submission::SUB_ID, :to_s, :to_s %>
<% end %>
where SUB_ID=[1,2,3] in model Submission
I want to implement a checkbox instead of a dropdown menu so that I can select multiple SUB_ID (i.e. 1&2 or 1&3 or 2&3 or 1&2&3). I tried to use this but it does not work:
<%= f.check_box :id, Submission::SUB_ID, :to_s, :to_s %>
Any idea?
Try this:
# view
<%= form_for(#submission) do |f| %>
<%= Submission::SUB_ID.each do |sub_id| %>
<%= f.checkbox 'ids[]', value: sub_id, checked: #submission.id == sub_id %>
<%= sub_id %>
<% end %>
<% end %>
# controller
params[:submission][:ids].each do |checked_sub_id|
# do your logic here
end
you have to iterate over SUB_ID
somehow like this...
<% Submission::SUB_ID.each do |ssid| %>
<%= f.check_box "ids[]", value: ssid %>
<% end %>
or you can use formtastic gem. it has :as=>:check_boxes input fields http://www.ruby-doc.org/gems/docs/n/nuatt-formtastic-0.2.3/Formtastic/Inputs/CheckBoxesInput.html
The core answer is you need to loop over each item in Submission::SUB_ID and make a checkbox for each id. Depending on how your models are set up and what you want to do - you may need to be much more involved in the form building. I hesitate to provide specific examples without know more about how you want the data to come back to the controller
<%= form_for(#submission) do |f| %>
<% Submission::SUB_ID.each do sub_id %>
<%= f.check_box_tag 'submission_ids[]', sub_id %>
<% end %>
<% end %>
Note that that will not default anything to checked and it does not come back as part of the submission parameters.
Usually when I have a similar situation I'm using nested forms to add or remove objects.
If you're using Rails 4, there is a new helper, collection_check_boxes, which helps streamline the building of your check boxes.
<%= f.collection_check_boxes :submission_ids, Submission::SUB_ID, :to_s, :to_s %>
Documentation:
Form builder version - which wraps...
...the general form options helper
If you look at the documentation in the second link, you'll also find how to use the optional block syntax to customise the HTML structure for each check box.
I want to be able to fill a table with some data through AJAX. My problem is that this data is from two different models. This will be long but please bear with me.
Imagine an application that would fill the plan for working out at the gym (clearly not an application for me :D). This plan has many routines (per type basis or day basis) which has many steps to go through.
Is it possible to use AJAX to fill a nice table that fills dynamically? Ideally I would prefer to save and display a table each time the user fills any new data.
What I have so far:
In the models I added the accepts_nested_attributes_for property.
I am using nested_form that allows us to add and remove nested models.
Let's take a look at our form:
app/views/plans/_form.html.erb
<%= nested_form_for #plan, :url => plan_path(#plan), :html => { :class => :form } do |f| %>
<%= f.label :name, "Plan Name" %>
<%= f.text_field :name %>
<%= f.fields_for :routines do |r| %>
<%= render 'routine_fields', :f => r %>
<% end %>
<%= f.submit %>
<%= f.link_to_add "Add a routine", :routines %>
<% end %>
So fields_for allows us to save many routines inside a plan, NICE! Let's define our fields views:
app/views/plans/_routine_fields.html.erb
<%= f.label :name, "Routine Name" %>
<%= f.text_field :name %>
<%= f.fields_for :steps do |s| %>
<%= render 'step_fields', :f => s %>
<% end %>
<%= f.link_to_add "Add a step", :steps %>
<%= f.link_to_remove "Remove this routine" %>
app/views/plans/_step_fields.html.erb
<%= f.label :name, "Step Name" %>
<%= f.text_field :name %>
<%= f.link_to_remove "Remove this step" %>
This works great! We can add as many routines inside a plan and many steps inside a routine we are able to create a complete plan in one view.
BUT IS UGLY! and also very confusing! So my problem again: How would I update the table each time the user fills any new data?
Ideal:
One approach that you could use for this would be to break up the form into different forms that are loaded via ajax, and just continuously update attributes on a model. You could also just use the form that you have now and break up the html so that it doesn't all show in a table.
For dealing with forms, you could check out the railscast on wicked
For dealing with ajax, there is a very good railscast on ajax/jquery
You could also break up this logic into different partials, and change the UX a bit, so that a user still has the same functionality, but it lives on a different view. You can add ajax to this by following the previously mentioned ajax railscast or using the turbolinks gem (though turbolinks is a bit different).
It seems to me that this is primarily a UX problem, and you're trying to crowbar a particular implementation into a rigid UX. I would try reframing the UX to see if there is a more elegant solution to the problems you have mentioned.
Im working with Rails 3.0.3
I want to create bills in my App. Each Bill has many entries (Material, how much of that and the Price)
The Problem i have, is that i want to write the bill and the entries and then save both at the same time. So when you click on save Bill, the Bill + each Entry should be created (saved in the db).
I can write the bill + each entry (with javascript), but i dont know how i could save both of them. Right now i can only save the bill it selft. Is it possible to pass a dynamic field via params so i can handle that in the bills controller to save? How would you implement this?
What you are looking for is called nested form, you have a main form for your bill and multiple forms that are dynamically generated as children of this general form using fields_for like this:
<% form_for #bill do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<% f.fields_for :entry do |builder| %>
<%= render "entry", :f => builder %>
<% end %>
<p><%= f.submit "Submit" %></p>
<% end %>
Of course you will need some js for the dynamic creation of the different entries, here you have a couple of railscasts that will be helpfull.
Nested model form Part 1
Nested model form Part 2