Select helper not showing value of selected option in search form - ruby-on-rails-3

In my Rails 3 app I use both checkboxes and, in one case, a select helper to submit a search form. I applied some jQuery to the form so if I click a checkbox, the form submits. Same with the select helper. If I click the checkbox, after the page renders the checkbox remains checked as an indicator of the parameters used to get the search result. The problem is that the select helper defaults to "Select" after the search form is submitted. It doesn't maintain the value of the params used to perform the search.
For example, say I have three options: "Select", "Arts", and "Vocational". If Select is the default in my form and I want to search by Arts, clicking "Arts" submits the form, refreshes the page, and the records matching "Arts" are rendered. However the select helper doesn't display "Arts". It defaults back to "Select" when the form is submitted.
I'm using Ransack to do the search, so here are the actions in my Controller where I'm performing the search:
def index
#q = User.search(params[:q])
#users = #q.result(:distinct => true)
end
def search
index
render :index
end
Here's my select helper:
<%= f.select :profile_subject_eq, options_for_select([['Select', ''], ['Arts'], ..., ['Vocational']], :selected => #q) %>
(As you can see I've tried to change the :selected to no avail.)
Finally, here's the jQuery I'm using to submit the form:
$(function(){
$('select').live('change',function() {
$(this).closest('form#index').submit();
});
});
UPDATE: Here is the HTML output of the select helper:
<fieldset>
<select id="q_profile_subject_eq" name="q[profile_subject_eq]">
<option value="nil">Select</option>
<option value="Arts">Arts</option>
...
<option value="Vocational">Vocational</option>
</select>
</fieldset>

Try
options_for_select([['Select', 'nil'], ['Arts'], ..., ['Vocational']], #q)
According to the API doc the second parameter is the selected item itself, not a hash like :selected => ...

If your set on using just select, then you can do it this way.
<%= f.select :profile_subject_eq, [["Arts"], ["Vocational"]], {:include_blank => 'Select', selected: params[:q] ? params[:q].try(:[], :profile_subject_eq) : ""} %>

Related

Use translation for submit button

I don't want to use the default
<%= f.submit %>
and have created a helper function for it, which also embeds an icon. The helper function expects a label to put on the newly created button.
I'm calling it like this:
<%= submit_button("icon-plus", I18n.translate("helpers.submit.create")) %>
But now on this text appears on the button:
%{model} toevoegen
Instead of:
Product type toevoegen
If I use the normal submit button then the correct text appears so my yml files are correct. How can I get the correct text to use in the helper?
Helper code:
def submit_button(icon, label)
link_to "javascript:void(0)", :class => 'btn btn-primary', :onclick => "$(this).closest('form').submit()" do
raw('<div class="') + icon + raw(' icon-white"> ') + label +raw('</div>')
end
end
As the I18n guide says, the translate function interpolates variables passed in the %{} brackets using its second argument (a hash).
In your case you need to tell it the model by doing this:
I18n.t("helpers.submit.create", model: "Product type")
If you want a generic option that would work for any model, you can see how Rails itself does it by looking at the source on GitHub - it's something like
I18n.t("helpers.submit.create", model: f.object.class.model_name.human)
As an aside, you don't need to (and probably shouldn't) use raw there. What you are trying to achieve could easily be done with the built-in helpers:
link_to ... do
content_tag :div, label, class: "#{icon} icon-white"
end

need rails like form_for tag in Rhodes

I was wondering if I can have something like form_for tag instead of the html tag in the edit.erb page in Rhodes. Because I have a Counter model with two attribs which I want to update them seperately based on the button pressed which resides right beside the value. I was able to do it in rails using the <%= form.submit 'up_a' %> & check which button was pressed in update method, like:
def update
#counter = Counter.find(params[:id])
if params[:commit] == 'up_a'
update_attri1 # simple increment method for attrib 1
elsif params[:commit] == 'up_b'
update_attri2 # simple increment method for attrib 2
end
end
and call that method to update that value.
So I want to have more control on what attribs I want to update based
on the clicks in form. Is there anyway I can achieve this in Rhodes?
EDIT :
The general problem seems to be that you want two submit buttons in a single form, each of which should do two slightly different things.
In the case that you only have two different values and one submit button for each, the simplest solution would be simply to make two forms that both call the update def (through their action-attribute), but each with their specific value of the query-parameter (in this case "commit"). These calls would have the following form:
<form method="POST" class="myForm" action="<%=url_for :controller => :Counter, :action => :update, :query => {:commit => 'up_a'}%>">
However, if you only want a single form (possibly also with many other input-values) there are several different ways to do it. In the following you will see a detailed implementation of one way to do it.
In this solution your buttons should NOT be submit buttons, but regular buttons (exactly how they are made with jQuery Mobile).
In order to make this solution work, you will need to use some javascript. You should therefore add the following javascript functions to your application.js and include it in your layout.erb.
function submitForm(formClass){
var activeForm = 'div.ui-page-active '+formClass;
$(activeForm).submit();
}
function callCounterSetUpdateAction(c){
$.get('/app/Counter/setUpdateAction', { commit: c});
}
Now that we have the needed javascript functions in place, lets take a look at edit.erb.
In this example Counter have three different attributes: a, b and c. We will however, only pay attention to a and b to begin with.
The form in your edit.erb file should be similar the implementation below. Notice, that the form actually doesn't have a submit button (as we will see later, the submit is actually made through our javascript function submitForm(formClass)).
<form method="POST" class="myForm" action="<%= url_for :action => :update %>">
<input type="hidden" name="id" value="<%= #counter.object %>"/>
<div data-role="fieldcontain">
<label for="counter[a]" class="fieldLabel">A</label>
<input type="text" id="counter[a]" name="counter[a]" value="<%= #counter.a %>" <%= placeholder( "A" ) %> />
</div>
<div data-role="fieldcontain">
<label for="counter[b]" class="fieldLabel">B</label>
<input type="text" id="counter[b]" name="counter[b]" value="<%= #counter.b %>" <%= placeholder( "B" ) %> />
</div>
<div data-role="fieldcontain">
<label for="counter[c]" class="fieldLabel">C</label>
<input type="text" id="counter[c]" name="counter[c]" value="<%= #counter.c %>" <%= placeholder( "C" ) %> />
</div>
<a data-role="button" data-transition="none" href="javascript:callCounterSetUpdateAction('up_a');">Update A</a>
<a data-role="button" data-transition="none" href="javascript:callCounterSetUpdateAction('up_b');">Update B</a>
</form>
Now that we have defined our view (edit.erb) lets take a look at the definitions we need our controller.
Firsly, as it can be seen from the href attribute on the buttons, what actually happens once we press a button is that it calls a javascript function which in turn calls the following def in the controller:
def setUpdateAction
$pressedButton = #params['commit']
WebView.execute_js("submitForm('.myForm');")
end
The purpose of this def is to store the parameter we sent from our button and then submit the form on the active page. Notice here that we added a class called myForm to the form shown above. You should also notice that we ensure that only the form on the active page is selected by adding 'div.ui-page-active ' to our formClass in the jQuery selection.
Finally, lets take a look at how your update definition should look like:
def update
#counter = Counter.find(#params['id'])
c = #params['counter']
if #counter
if $pressedButton == 'up_a'
# Update value A.
#counter.update_attributes(
{"a" => c['a']}
)
elsif $pressedButton == 'up_b'
# Update value B.
#counter.update_attributes(
{"b" => c['b']}
)
end
end
redirect :action => :index
end
It should be noticed here that we select which attributes to update based upon the $pressedButton variable we assigned through setUpdateAction. As a final comment we could also update multiple attributes as seen below (where we also update the 'c' attribute).
#counter.update_attributes(
{"b" => c['b'],"c" => c['c']}
)

Humanize rails select helper

I have the following in my model:
PRODUCTSTATES = %w[published coming_soon in_development cancelled]
I'm using that to populate a drop-down in a form, and I'm trying to use humanize to make the list look pretty, but can't seem to get it.
<%= f.select :status, Product::PRODUCTSTATES %>
Product::PRODUCTSTATES.humanize obviously doesn't work, nor does converting to a string before hand.
You can pass an array like
[['caption1', 'value1'], ['caption2', 'value2']]
to select helper and it'll generate smth like
<select>
<option value="value1">caption1</option>
<option value="value2">caption2</option>
</select>
In your case you can do like that:
<%= f.select :status, Product::PRODUCTSTATES.map { |s| [s.humanize, s] } %>
You'll get humanized versions of the statuses displayed on the page and the original (non-humanized) versions will be sent to the server when the form is submitted.
See select and options_for_select docs for more information.

Reload calendar into nested forms (rails 3)

I have a form which contains one model (let's call it Model1) and this models accepts nested attributes from another one (let's call it Model2). I want to be able to save many Model2 records, but I want the view, at the beginning, to show just one set of fields from Model2, and have a button which, if clicked, displays another set of fields from that model, and so on. For this, i'm using the nested_form gem.
All is working well, but the problem is that one of the fields is associated with a datepicker. So, the first Model2 set of fields shows the calendar, but when I click to render the next set of fields, the datepicker, of course, does not get shown anymore (because the Javascript loads only when you get to the page and never again)
The following code shows the button which adds more concepts (Concept is Model2)
<%= f.fields_for :concepts do |concept_form| %>
<%= render "courses/concept_fields", :f=>concept_form%>
<% end %>
<p><%= f.link_to_add t("concepts.add"), :concepts %></p>
And inside courses/concept_fields I have:
<%= f.text_field :collection_date, :value => f.object.collection_date, :class => 'text date_picker tabs' %>
The javascript for the datepicker is included in the layout
Is there any way you can help me? Thanks!
Add and click event handler to the button you use to render the next set of fields to reload the datepicker something like:
$('.render_next_button').click(function(){
// code to reload datepicker
$( "#datepicker" ).datepicker();
});
I've found an answer which solved my problem. It's in this link:
jQuery UI DatePicker with nested_forms Gem
Would look like this:
<script type="text/javascript">
jQuery(function() {
jQuery('form').live('nested:fieldAdded', function(event) {
jQuery(event.field).find('.date_picker').removeClass('hasDatepicker').datepicker();
});
});
</script>

How to redirect from one form to another and passing a value to the second form?

I have a "mini" form on the home page which allows the user to select a car color and press submit.
After doing so, the user is taken to another form where the previously selected car color is used to
pre-populate a field in this other form.
The mini form is this:
<%= form_tag('/cars/new', :method => :get) %>
<%= select "new_car", "color_id", Colors.find(:all, :order => "description asc").
collect {|s| [ s.description, s.id ] }, {:include_blank => 'Select color'} %>
<input type="submit" value="Submit"/>
On pressing submit, this routes to the correct action (/cars/new) but the URL in the address bar is:
http://localhost:3000/cars/new?utf8=✓&new_car[color_id]=12
Where I expected it to be:
http://localhost:3000/cars/new?color_id=12
How to make get the URL to look like the one above?
Another question, how exactly is the form_tag to be used? How do you put a closing </form> tag?
For the block form of form_tag, see:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-form_tag
For the query string issue, there's a similar question here:
removing "utf8=✓" from rails 3 form submissions