unescape HTML in options for select - html

I've got a select tag, which is used to change the filter via the URL. On change I reload the page to update the results accordingly. The newly selected filter should obviously appear as selected. But this fails to work.
<%= select_tag("filter_rating" , (:selected =>) options_for_select(rating_filter_options, (request.env['PATH_INFO']))) %>
I deleted the (:selected =>) as it seems unnecessary.
rating_filter_options value:
# [["by my rating", "/all"], ["1+", "/rating%3E=1"], ... , ["5", "/rating%3E=5"]]
The reason why the current filter will not get selected is that request.env['PATH_INFO'] returns /rating>=1, which is different than /rating%3E=5. So the solution would be to unescape that nasty %3E.
I tried using CGI.unescape, h, html_safe on the select tag, but so far my attempts have failed.
Any ideas?
Update:
I changed the helper that generated the rating_filter_options and placed the CGI.unescape correctly so it now returns:
# [["by my rating", "/all"], ["1+", "/rating>=1"], ... , ["5", "/rating>=5"]]
Also, I use CGI.unescape for the request.env['PATH_INFO'] to make sure it is the same. The result in logs & HTML approve that it is correct now. BUT the selected filter still does not get selected...

CGI should work.
irb(main):112:0> CGI.unescape("/rating%3E=1")
=> "/rating>=1"

Related

How to select from a selection box with a variable in the name?

I am having trouble using selecting from this select element.
<select name="vehicle_attrs[position_count]" class="mb1"><option>Position / Quantity</option><option>Front</option><option>Rear</option></select>
I have tried
select('Front', :from=>'mb1')
select('Front', :from=>'vehicle_attrs[position_count]')
select('Front', :from=>'vehicle_attrs[1]')
All of them result in a can not find selection box error
I've never liked how restrictive Capybara's concept of a 'locator' is (i.e. must have a name/id/label), but if you dig into the source code, those helpful methods like select, click_on, and fill_in are just wrappers for find and some native method of Element, which takes arbitrary CSS, and works in almost all situations. In this case, you could use:
find('[name="vehicle_attrs[position_count]"]').find('option', text: 'Front').select_option
Since dropdowns often have multiple similar options, where one is a substring of the other, you might consider using an exact string match, like
find('[name="vehicle_attrs[position_count]"]').find('option', text: /\AFront\z/).select_option
From the docs for select - https://www.rubydoc.info/github/teamcapybara/capybara/Capybara/Node/Actions#select-instance_method - we can see that the from option takes "The id, Capybara.test_id atrtribute, name or label of the select box".
Neither 'mb1' or 'vehicle_attrs[1]' are any of those so they would be expected to fail.
'vehicle_attrs[position_count]' is the name so assuming the box is actually visible on the page (not replaced with a JS driven select widget, etc), that should work. If it doesn't, then edit your question and add the full exact error message you get when trying to use it. Of course if there is only one select box on the page with an option of 'Front' then you don't need to specify the from option at all and can just do
select 'Front'

generate subscript in controller and pass to view

In controller, I can pass string to view.
How can I pass string with subscript?
In html its easy, just use a <sub> tag.
I tried 3 times to pass this subscript to view but failed.
If I pass <sub> inside the string, it will display I<sub>tag</sub> instead of Itag.
If I use string1="string"+<sub>+"tag"+</sub> ,and pass
string1, The controller will give error!
Last, I tried directly to copy subscript string inside the page, I
also got an error that it can't get displayed.
How can I pass subscript string to view? I got to loop different conditions so I cant each use <sub> tag, I need pass from controller.
Edit:
I tried this code in controller
#valuedisplay=#value.to_s + " m/s<sup>2</sup>".html_safe
As suggest solution ,and I get:
Just as what I said in 1st try,display the <sup> instead of m2.
If I do it in view,I have many different types of data ,I need add checking data type code in view according to different types,its doable but will make the view messy, I felt there should be a neat way to settle it in controller?
You need to safely render the HTML in your view, and for this purpose, you need to call html_safe function on your string:
#str = "I<sub>tag</sub>".html_safe
And, now when you pass this #str to your view, it will render the #str as expected.
In view:
<%= #str %>
Caution:
It would be a very bad practice to do so. <sub>ag</sub> belongs to view, so it should be in view. You can do something like following:
In controller:
#str = "tag"
And in view:
I<sub><%= #str %></sub>
<%# or %>
<%= "I<sub>#{#str}</sub>" %>

Need Validation on html dropdownlist with data from Viewbag

I know I'm not supposed to use the Viewbag and that I should build a menu using Html.DropDowlListFor() so that i can add attribute bound to the members of the model, BUT, that would involve a pretty extensive code rewrite....
I have a custom controller with a menu:
*.ASCX
<%: Html.DropDownList("CityIDs", new SelectList(ViewBag.cities, "Id", "Name"), "--Select--", new { style = "width:200px" })%>
<%= Html.ValidationMessage("CityIDs") %>
The List populates just fine and I can default to the top item to "--Select--"
The prbolem is that I want the validation error to occur on anything that is not from the viewbag.... how can I achieve this?
Validation for dropdown lists only ensures that something was posted. If you want to ensure that the value that was posted is actually one of a set of "allowed" values, then you'll have to manually do that in your post action:
var cityIds = db.Cities.Select(m => m.Id);
if (!cityIds.Contains(model.CityIDs))
{
ModelState.AddModelError("CityIDs", "You must select one of the available choices.");
}
if (ModelState.IsValid)
{
...
Two things:
Notice that I'm pulling the city ids straight from the database (the actual code you'd need here, of course, depends on your specific implementation). The important thing, though, is that ViewBag only survives a single request, so you can't look for them in ViewBag after posting.
Despite the pluralized name of CityIDs, using the DropDownList helper ensures that only a single selected value will exist. If this is actually supposed to be a multiselect, then you need to use ListBox instead, and update this conditional here to account for check for multiple values.
Populates the top item with Text = "--Select--" and Value = ""
which will post a blank value for CityIDs and cause an error in ModelState.

Rails form_for setting options and setting selected option

Another simple question i'm sure so sorry in advance but i cant seem to find a solution to what i am trying to do.
I have form with a select field (vehicle_size) that i want to populate with all existing options that are currently in the database for records that have vehicle_size set. I also want to set the selected option to whatever the option in the database is currently set to (if set) but i guess the problem that i am having is the reason that this value isn't being set already.
I currently have this code:
<%= f.select(:vehicle_size, #models.index_by {|m| m.vehicle_size}, :selected => :vehicle_size) %>
which is populating the select options correctly but in my new and edit pages (both using this form) the select menu is blank even though currently all records are be set to one of the existing options (vehicle_size may actually be blank for some records in future).
If i then select an option from the menu and save the record the vehicle_size option has a strange value. something along the lines of :
#<Model:0x007fd13e6c3790>
I'm pretty sure i'm using index_by in the wrong way so some pointers on what i'm missing would be great.
The parameters of f.select are: attribute_name,option_tags,options.
option_tags is supposed to be a string of html option tags.
There are some helpers to construct such a string from i.e. an array of values, a collection etc.: options_for_select, options_from_selection_for_select.
You have to use one of these helpers.
You can get the existing vehicle_sizees with:
Model.pluck(:vehicle_size).uniq
so your select could look like:
<%= f.select :vehicle_size, options_for_select(Model.pluck(:vehicle_size).uniq,#model.vehicle_size) %>
See the Rails Guide on form helpers.

Disable DropDown in Rails

I want to disable an HTML DropDown in Rails, and I found this solution:
how to disable the entire dropdown control in html
So, I have this:
f.select( ...., :disabled => true)
But, the problem is, when the DropDown is disabled, it does not show in the params collection.
EDIT:
This is my situation:
I have a form with a text_field and a select field. There are two cases:
The user creates a new item directly. If so, she will choose a category from the select field.
The user creates a new item, after redirecting from a category page. In this case, the select field is set to the value of the category, and should be disabled.
Does anyone have any idea how to fix this?
As mentioned in my comment in the original question, disabled form element values won't be present in the params on a form submission. To get around this, try using a hidden field to hold and submit the value you want.
Assuming some variables and whatnot are setup to help decide whether the select field should be disabled:
# ...
f.select(..., :disabled => #category_already_chosen)
f.hidden_field(...) if #category_already_chosen
# ...
Obviously this can be changed to suit your needs, but the basic idea is there. If you've already chosen a category and want the select field to be disabled, make a hidden field. If you haven't chosen a category, omit the hidden field and allow users to make use of the select field.
As shown in the link I posted, this is probably the simplest way to get around this limitation, without resorting to using Javascript to play with parameters after form submission.
I would add query string parameters to your redirect_to call
redirect_to :action => form_path, :category => :whatever_category_they_came_from, :disabled => true
Then in your form
:selected => params[:category], :disabled => params[:disabled]