I have private method on controller
private
def set_address
#address = Address.find(params[:id])
end
def city_options
#city_options = []
if #address
#city_options = City.where(province_id: #address.province_id).collect{ |x| [x.name, x.id] }
end
end
And on views of _form.html.erb
<%= f.select :city_id, #city_options, { :prompt => I18n.t('prompt.select_city') }, class: 'select-city text address-city' %>
It's fine on new form and edit has right selected value, but when I encrypt the id in city_options method
#city_options = City.where(province_id: #address.province_id).collect{ |x| [x.name, encrypted_id(x.id)] }
List of city is shown and value of id is encrypted but wrong selected a value of city, just selected id on top of list.
Wrong value is selected because the saved city_id do not match the encrypted_id of any select list option.
To get over it you can use options_for_select method. Try following if encrypted_id method is a helper method
<%= f.select :city_id, options_for_select(#city_options, selected: encrypted_id(f.object.city_id)), { :prompt => I18n.t('prompt.select_city') }, class: 'select-city text address-city' %>
Check this link http://apidock.com/rails/v3.1.0/ActionView/Helpers/FormOptionsHelper/options_for_select
If encrypted_id method is a controller method, you have pass currently selected value by encrypting it from controller. Or you can use
helper_method :encrypted_id in controller to make encrypted_id method available in view and can use above mentioned method
Related
I created a rails (v5) form with multiple select and collection_select elements.
Then I use Select2-rails (v4.0.3) to allow a nice selection looking like tags.
The search-options are pulled by ajax.
It works fine until one presses the submit-button with missing required fields.
Valid field-content has now been deleted from the field.
Let me give some example-code:
controller:
...
def form
if params[:form_request].nil?
#form_request = FormRequest.new
else
#form_request = FormRequest.new(params[:form_request])
end
end
def request_form
#form_request = FormRequest.new(params[:form_request])
if #form_request.valid?
render :summary
else
render :form
end
end
...
form:
...
<%= bootstrap_form_for(#form_request, url: '/form/request_form') do |f| %>
<%= f.select :field, [], {label: 'Field label'} %>
<%= f.submit "Submit form" %>
<% end %>
:field is for sure a writable field in the model (and data is set fine)
coffee-script:
Query ->
$("#form_request_from").select2({
ajax: {
url: func =(params) ->
filter = params.term
return "/data.json?filter=" + filter;
,
dataType: 'json',
processResults: processData
},
theme: 'bootstrap',
placeholder: 'Enter data here'
});
processData = (data) ->
mapdata = $.map(data, func =(obj) ->
obj.id = obj.id;
obj.text = obj.name;
return obj;
);
return { results: mapdata };
I am thinking of a lot of possibilities, but at the end I am not sure where the field-data comes from. It is inside the object, but it isn't written to the resulting HTML in any way.
And even if the id would be written as a selected option,
the select2 script would need to know how to transform that into the string to show the real data.
Any idea how to achieve that the data is still written into a field after a failing validation?
After trying out some things I found out how to do it.
At first I just changed the empty array to be the :field variable,too.
This doesn't work too well because it only remembers the ID of the value that has been entered before and like this the SELECT2-script could not find the value to that key and nothing is shown.
Then I created a new variable inside the controller in which I place the array with name and id:
field_object = ObjectsModel.find(#form_request.field.to_i)
#form_field = []
if !field_object.nil?
#form_field = [[field_object.name, field_object.id]]
end
And in the view I now use this field to show the available options:
<%= bootstrap_form_for(#form_request, url: '/form/request_form') do |f| %>
<%= f.select :field, #form_field, {label: 'Field label'} %>
<%= f.submit "Submit form" %>
<% end %>
This works perfectly fine for me without the need to touch the SELECT2-script.
The possible values are still fetched by AJAX but already filled out fields will persist upon redirect to another action.
I have the following code in my rails app:
<%= select :object,
:id,
options_for_select(Hash[#object_list.map { |object| [object.name, object.id] }]),
{:include_blank => 'Please select...'},
{} %>
If no option is selected then in my controller I receive an empty string.
How can I make the options for select send 'nil' value instead?
I think you can achieve that by inserting nil in your list.
<%= select :object,
:id,
options_for_select(Hash[#object_list.map { |object| [object.name, object.id] }].merge({:0 => nil}), selected: 0) %>
You should use before_action callback for your controller.
class SomeController
before_action :prepare_params
private
def prepare_params
params[:your_param] = nil if params[:your_param].blank?
end
end
I'm using Rails 4.0.2 with jquery-rails (3.1.0) and jquery-ui-rails (4.1.1) gems. I'm added autocomplete in order to do a specific search based on what user typed and other fields at form.
The form:
<%= text_field_tag :field , some_value, data: { autocomplete_source: select_path( { :id => #order.Id , :type => #order.type } ) } %>
Form.js:
$('#field').autocomplete
minLength: 0
source: $('#field').attr('data-autocomplete-source')
select: ( event, ui ) ->
$('#pedido_venda_CodTransp').val(ui.item.value)
$('#transportadora_escolhido').val(ui.item.label)
this.form.submit()
false
...
The controller:
def select
# retrieve parameters
id_cliente = params[:id]
retira_entrega = params[:type]
term = params[:term]
# do the query, etc...
end
When I run the code, everything is OK. The controller receives all parameters and run the query flawlessly.
The parameter type, however, is based on a SELECT control and, in order to change it, I put the following code in the SELECT control.
<%= f.select :type, options_for_select( [['RETIRA','R'],['ENTREGA','E']] , #pedido.RetiraEntrega ) ,{}, { :onchange => "change_type();" } %>
JS Code function:
function change_type()
{
var e = document.getElementById("type");
var option = e.options[ e.selectedIndex ].value;
var field = document.getElementById("field");
var origem = "type=";
source = field.attributes["data-autocomplete-source"].value;
// pesquisa a string retira_entrega=
index = source.search(origem);
field.setAttribute("data-autocomplete-source", source.substring(0,index+origem.length) + String(option));
}
The JS function is called, the last line is run, the attribute is set (I put an alert at the end retrieving the attribute).
The problem is that the controller never receives the changed value (it always receives the value when the form is created).
So, the question is: how can I change a parameter passed on to autocomplete in order to use it in rails controller?
Not sure if this is what your looking for but I was struggling with the same issue because I had two input fields that I wanted different lists loaded to in the autocomplete widget. So what I did was pass an extra param to the auto complete source like this:
<!-- /_form.html.erb -->
<%= f.text_field :auto1, :size => "100", class: "form-control", data: { autocomplete_source: root_path(:fieldType => "numerouno")} %>
<%= f.text_field :auto2, :size => "100", class: "form-control", data: { autocomplete_source: root_path(:fieldType => "numerodos")} %>
Then in my controller I used that extra param to determine which list I needed to show:
if param[:fieldType] == "numerouno"
format.json { render :json => #unoList}
elsif param[:fieldType] == "numerodos"
format.json { render :json => #dosList }
else
flash[:danger] = "Error loading list for autocomplete!"
end
param[:term] still goes through too!
<%= collection_select(:catgory, :id, #categories, :id, :title, {}, data: { behavior: 'category_dropdown' }) %>
In the above code I need to pass a parameter to the title method. Is there any way to do this with collection_select?
<%= collection_select(:catgory, :id, #categories, :id, (:title, #program), {}, data: { behavior: 'category_dropdown' }) %>
Edit:
Looking at the internals for collection_select the text_method. It is eventually passed to a .send method which should allow for element.send(:title, #program). However, I think the issue why I still can't pass the param is that collection select is reading (:title, #program) as two params instead of one.
Use select instead:
select "catgory", "id", #categories.map{|c| [c.title(#program), c.id]}, {}, data: { behavior: 'category_dropdown' }
Should be working.
This can be done with collection_select if your model has an existing parameter you can overwrite:
f.collection_select( :your_model_id,
YourModel.all.map{|ym| ym.name = ym.custom_name(your_parameter); ym},
:id, :name,
{:selected => #model_instance.logic},
{:class => 'your class', :other => "..." } )
For instance I do this to conditionally pluralize my model's name attribute
class MyModel < ActiveRecord::Base
DEFAULT_NAME_COUNT = 99
def pluralized_name(n = DEFAULT_NAME_COUNT)
begin
return name.pluralize(n)
rescue
end
name
end
end
I have the following problem. I have a form which takes input for a "Chart" object. But after processing the form, i wish to display one of the values, and it adds the key of this value.
Class model
class Chart
attr_accessor :title, :series
def initialize(title = nil, series = [])
#title, #series = title, series
end
end
View of form:
<% form_for :chart , :url => { :action => "show" } do |f| %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>...
<% end %>
Chart controller, show method:
def show
#chart = Chart.new(params[:chart])
end
View of show:
<h2><%=h #chart.title %></h2>
Which displays: "title"input_forms_title""
for example: writing in the input form: Economy, prints in the show view: "titleEconomy"
Any ideas?
I have just figured it out. The problem was in the constructor or initialize method. By changing the initialize method to:
def initialize( options = {} )
#title = options[:title]
#series = []
end
It now accepts all params perfectly!