Rails simple_form collection to %ul? - ruby-on-rails

so I will get right into asking.
This is an input from my simple_form
= f.input :focus, collection: [[t('alg.focus.execution'), 'Execution'], [t('alg.focus.management'), 'Management'], [t('alg.focus.client'), 'Client'], [t('alg.focus.development'), 'Development']], :wrapper => :inline_checkbox, :include_blank => false, label: t('recruiter.jobs.new.focus')
and the output in html is this
<div class="select required job_focus">
<select class="select required" name="job[focus]" id="job_focus">
<option value="Execution">Execuție</option>
<option value="Management">Management</option>
<option value="Client">Client</option>
<option value="Development">Dezvoltare</option></select></div>
Now what I want to do is to change the select tag into ul and option into li, this way I can customize the drop down menu as I want.
I have found a way in simple_form, that you can add a wrapper class to tag or to use another tag instead of other tags, but as I have seen is only limited to some tags like input, label, error etc. But I could not found how to change select and option.
by adding this element to the input :wrapper => :inline_checkbox,
and by adding this into simple_form.rb this
config.wrappers :inline_checkbox, :error_class => 'error' do |b|
b.use :html5
b.use :input
b.use :label
b.wrapper :tag => 'div', :class => 'controls' do |ba|
ba.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
ba.use :hint, :wrap_with => { :tag => 'p', :class => 'help-block' }
end
end
So I need your help.
Thank in advance.

You're looking at this the wrong way. SimpleForm isn't build to do the kind of thing you're looking for. It's built to make forms. I get that you're trying to fake a <select> with a <ul> but that's not typical form behavior.
You'll just want to create the <ul> using normal view helper methods. Then, you'll need to use JS to make any stage changes are saved to a hidden input field that will get POSTed with the rest of your form.
Example in Jquery
function customSelect(){
// Iterate over each select element
$('select').each(function () {
// Cache the number of options
var $this = $(this),
numberOfOptions = $(this).children('option').length;
// Hides the select element
$this.addClass('s-hidden');
// Wrap the select element in a div
$this.wrap('<div class="selects"></div>');
// Insert a styled div to sit over the top of the hidden select element
$this.after('<div class="styledSelect"></div>');
// Cache the styled div
var $styledSelect = $this.next('div.styledSelect');
// Show the first select option in the styled div
$styledSelect.text($this.children('option').eq(0).text());
// Insert an unordered list after the styled div and also cache the list
var $list = $('<ul />', {
'class': 'options'
}).insertAfter($styledSelect);
// Insert a list item into the unordered list for each select option
for (var i = 0; i < numberOfOptions; i++) {
$('<li />', {
text: $this.children('option').eq(i).text(),
rel: $this.children('option').eq(i).val()
}).appendTo($list);
}
// Cache the list items
var $listItems = $list.children('li');
// Show the unordered list when the styled div is clicked (also hides it if the div is clicked again)
$styledSelect.click(function (e) {
e.stopPropagation();
$('div.styledSelect.active').each(function () {
$(this).removeClass('active').next('ul.options').hide();
});
$(this).toggleClass('active').next('ul.options').toggle();
});
// Hides the unordered list when a list item is clicked and updates the styled div to show the selected list item
// Updates the select element to have the value of the equivalent option
$listItems.click(function (e) {
e.stopPropagation();
$styledSelect.text($(this).text()).removeClass('active');
$this.val($(this).attr('rel'));
$list.hide();
/* alert($this.val()); Uncomment this for demonstration! */
});
// Hides the unordered list when clicking outside of it
$(document).click(function () {
$styledSelect.removeClass('active');
$list.hide();
});
});
}
and then just call this function wherever you need, on a click, when the document is ready.

You can use https://github.com/Slashek/bootstrap-select-rails gem and simply add selectpicker class to the input_html.
An example such as
<%= f.input :sharing_policy,
label: t('portal_new.privacy.share_designs'),
collection: sharing_policy_options,
selected: current_school[:sharing_policy],
include_blank: false,
include_hidden: false,
input_html: {class: 'selectpicker'}
%>

Related

Select box doesn't show selected value

I have a select box like this, it works and is saved in the database, but after I refresh the page the selected value doesn't appear as selected. Any suggestions?
.col-md-6
%span.label.label-purple{:style => "pointer-events: none; font-size: 14px"} Country Default
= select_tag :country_default, options_for_select(Location.where(loc_type: "country").map { |country| [country.name, country.loc_code] }),
style: "margin-top: 11px;",
include_blank: "",
class: "country-default select2", data: { select: "select2"}
options_for_select has an optional second argument, which will display your selected option, if one has been selected.
...options_for_select(Location.where(loc_type: "country").map { |country|
[country.name,
country.loc_code]}, #YOURMODEL.country_default)...
Use collection_select instead of select_tag like this:
=collection_select :country, :default, Location.where(loc_type: "country"), :loc_code, :name,
{include_blank: '', selected: 'select2' },
{class: 'country-default select2', style: 'margin-top: 11px;'}
another option is using select to generate select boxes.
See the Action View Helpers Guide

If Else in HAML to check the value of a "select" box

= form_tag questions_path, :method=>:post do
= label :question, :type, 'Type: '
= select :question, :type, %w(Text Picture Audio Video), :id=> :question_type_combo
**- if :question_type_combo.selected != 'Text'**
= label :question,:url, 'URL: '
= text_field :question,:url, :id=> :question_url_text
= submit_tag 'Add Question',:id=>:add_question_button
Is something of this sort possible in HAML? I wish to render the textfield only for certain options if selected in the SELECT BOX above.
Yes and no. You can write a conditional based on the values of the record that you bind to the form:
= form_for #question do |f|
= f.label :type
= f.select, :type, %w(Text Picture Audio Video), id: 'question_type_combo'
- unless f.object.question_type_combo === 'Text'
= f.label :url
= text_field :url, id: 'question_url_text'
But this would only change the visibility after the user submits the form and not be very useful.
Instead you can just use jQuery to create an event handler for the ´change´ event.
$(document).on('change','#question_type_combo', function(){
var type = $(this).first(':selected').val();
var $other_input = $('#other_input');
if (type == 'Text') {
$other_input.hide();
} else {
$other_input.show();
}
});
// sets the initial state
// if you are using turbolinks
$(document).on('page:load', function(){
$('#question_type_combo').trigger('change');
});
// if you are not using turbolinks
$(function(){
$('#question_type_combo').trigger('change');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<div class="field">
<label>Type</label>
<select name="question[question_type_combo]" id="question_type_combo">
<option>Text</option>
<option>Something else</option>
</select>
</div>
<div class="field" id="other_input">
<label>URL</label>
<input type="text" name="question[url]">
</div>
</form>
- if :question_type_combo.selected != 'Text' This is not possible in the haml view, If you want to do something based on selected option you have to use js.
Or you may set the selected option using similar code if you have controller objects:
= select_tag("fee_discount", options_for_select(Fee.discounts.keys.map {|k| [k.titleize, k]}, selected: "#{"rewards" if #vendor.present? && #vendor.approved?}"), include_blank: true)
Or
You may keep the label and text_field inside a div with hide class.
And then using javascript you may hide unhide the div.

Select option required Ruby Rails

I have a mix of ruby rails code
I have a form with a selection option that i want to be a required, and i want to validate. If user do not select anything i want to validade with a error message.
However, I try to copy past code from internet, I'm new at ruby rails and I still not have a error message.
I also check that i use 'required' , or if i use 'validates_presence_of' doesn't make difference because it's a submit form (i think)
test_filteR_form.rb
class TestFilterForm < ApplicationForm
attribute :model, String
validates_presence_of :model
end
.html.erb
<%= f.input :fill_form_error_message,:as => :hidden, :input_html => { :value =>I18n.t('test.fill_form_error') } %>
<%= f.input :model, label: I18n.t('test.filters.model'), autofocus: true, input_html: {class: 'input-xlarge chosen-select' }, collection: TestType.options_for_select, include_blank: true %>
"/>
controller
def paginate
#test_form = TestForm.new(params)
unless #test_form.valid?
#model = params[:test_filter_form][:model]
#h_model = #model.pluralize + 'H'
#history, _query, #test_fields = TestQueryService.search!(params)
session[:test_query] = _query
session[:test_klass] = #model
else
format.json { render :json => { :error => #test_form.errors.full_messages }, :status => 422 }
end
js.coffee
$contentDiv.on 'ajax:error', 'form[data-value]', (event, xhr, status, error) ->
data = $.parseJSON(xhr.responseText)
$result = $(#).parents('tr').find('[data-result]')
controller.resultUpdateError xhr.status, $result.data('result'), data, $(#)
# Hide row loading spinner
$(#).parents('tr').find('span[role="result_update_spinner"]').hide()
# Hide saved form
$(#).parents('tr').find('.saved_form').hide()
resultUpdated: (result, data, $form) ->
if data.flash != undefined
# Sets a sucess message on page top
flash data.flash.type, data.flash.message
# Sets a success message on row
$fieldForm = $form.parents('tr').find(".messages")
$fieldForm.find('.controls').empty()
$fieldForm.find('.control-group .controls').css('color', 'green').append #_inlineMessage("Gravado com sucesso")
# Hide success message after some time
setTimeout ((self) ->
->
$fieldForm.find('.control-group .controls').empty()
return
)(this), 4000
Since you are dynamically created the selection box then there must be a default value selected which is not nil so there is no change seen you can manually create selection like this:
<div class="form-group">
<%= f.label :select_user_country %><br/>
<select class="form-control select2" name="user[country_id]">
<option value="" selected disabled>Select a Country</option>
<%#countries.each do |country|%>
<option value="<%=country.id%>"><%=country.name%></option>
<%end%>
</select>
</div>

Hide submit button before text is entered

Trying to simply hide the submit button before text is entered but nothing seems to be happening. (Something in the coffeescript is wrong but i don't know what - very new to js)
My form looks like this:
<%= f.input :body, as: :text, input_html: { :id => "inputBody" } %>
<%= f.submit "Answer", { :id => "button" }%>
Coffeescript looks like this:
$(document).ready ->
$("#button").hide()
$("#button").show() if $("#inputBody").length > 0
I do not know CoffeScript but in JavaScript You can try something like this:
$(function(){
$("#button").hide();
$("#inputBody").keyup(function() {
var val = $(this).val();
if (val.length > 0) {
$('#button').show();
}
else {
$('#button').hide();
}
});
});

best_in_place gem: styling OK button

best_in_place is working well but I'd like to use fontawesome icons for the optional "OK" button, rather than a string. How can I incorporate the '<i class="icon-ok"></i>'.html_safe syntax in the :ok_button hash?
= best_in_place #book, :default_price_amount, :html_attrs => {:class => 'medium_no_dropdown'}, :ok_button => "OK"
This is an old question, and the desired functionality is now supported in the best_in_place gem using the :ok_button_class option. Usage is like this:
<%= best_in_place #post, :title, :ok_button => "Submit", :ok_button_class => "btn post-title" %>
There is a solution , but not exactly to add a style to the ok_button . If you don't mind to use unicode glyphs , you can try :
= best_in_place #book, :default_price_amount, :html_attrs => {:class => 'medium_no_dropdown'}, :ok_button => "✓".html_safe
The table with all the unicode characters could be your reference for another variant .
The problem with the real styling of ok_button is that the hash is accepting data-attribute only for defining of the button . Probably in one of the next versions of BIP this will be improved.
In the source code, where the button is created (best_in_place.js):
if(this.okButton) {
output.append(
jQuery(document.createElement('input'))
.attr('type', 'submit')
.attr('value', this.okButton)
)
}
'value' is what we pass on the hash . If there is a way to make a reference to the glyph-codes , defined by awesome font ( for icon-ok ) , it would be beautiful .
Since I spent couple hours to do the same thing, I found that we can override the prototype of this function to create <button> instead of <input type="button">. However, the activateForm function only wait for click event from input[type="button"] and since I can't override it, so I try another (a bit dirty) way – and it works.
Overwrite this script at another js tag/files
BestInPlaceEditor.prototype.placeButtons = function (output, field){
'use strict'
// the ok button isn't changed
if (field.okButton) {
output.append(
jQuery('<button>').html(field.okButton).attr({
type: 'submit',
class: field.okButtonClass
})
)
}
if (field.cancelButton) {
// create new cancel "<button>"
var $resetBtn = jQuery('<button>').html(field.cancelButton).attr({
type: 'reset',
class: field.cancelButtonClass
}),
// and traditional cancel '<input type="button">', but this should be hidden
$_resetBtn = jQuery('<input>').val(field.cancelButton).css({ display: 'none' })
.attr({
type: 'button',
class: '__real-btn-close-best_in_place'
});
// and bind event to 'trigger' click traditional button when the new <button> is clicked
$resetBtn.bind('click', function (event) {
$(event.currentTarget).parents('form.form_in_place').find('input.__real-btn-close-best_in_place').trigger('click');
event.stopPropagation(); // << also neccessary
});
// append both
output.append($_resetBtn).append($resetBtn);
}
}
}

Resources