{"id":24987780,"url":"https://github.com/jdugarte/rails-bootstrap-form-extensions","last_synced_at":"2026-05-05T23:33:37.604Z","repository":{"id":62554475,"uuid":"42951377","full_name":"jdugarte/rails-bootstrap-form-extensions","owner":"jdugarte","description":"Specialized controls added to the bootstrap_form gem","archived":false,"fork":false,"pushed_at":"2019-06-22T16:26:34.000Z","size":252,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-12T21:10:26.292Z","etag":null,"topics":["bootstrap","bootstrap-form-builder","duration","rails","rails-form-builder","ruby","schedule","timespan"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdugarte.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-09-22T18:02:01.000Z","updated_at":"2019-06-22T16:26:01.000Z","dependencies_parsed_at":"2022-11-03T05:00:37.302Z","dependency_job_id":null,"html_url":"https://github.com/jdugarte/rails-bootstrap-form-extensions","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/jdugarte/rails-bootstrap-form-extensions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdugarte%2Frails-bootstrap-form-extensions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdugarte%2Frails-bootstrap-form-extensions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdugarte%2Frails-bootstrap-form-extensions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdugarte%2Frails-bootstrap-form-extensions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdugarte","download_url":"https://codeload.github.com/jdugarte/rails-bootstrap-form-extensions/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdugarte%2Frails-bootstrap-form-extensions/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32672675,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-05T11:29:49.557Z","status":"ssl_error","status_checked_at":"2026-05-05T11:29:48.587Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bootstrap","bootstrap-form-builder","duration","rails","rails-form-builder","ruby","schedule","timespan"],"created_at":"2025-02-04T11:55:55.040Z","updated_at":"2026-05-05T23:33:37.585Z","avatar_url":"https://github.com/jdugarte.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"If you are using Bootstrap v3, refer to the legacy [legacy-1.2.1](https://github.com/jdugarte/rails-bootstrap-form-extensions/tree/legacy-1.2.1) branch.\n\n---\n\n# Rails Bootstrap Form Extensions\n\n**Table of Contents**\n\n- [Requirements](#requirements)\n- [Dependencies](#dependencies)\n- [Installation](#installation)\n- [SubmitBar](#submitbar)\n\t- [Configuration](#configuration)\n\t- [Default partial](#default-partial)\n- [Duration](#duration)\n  - [Duration without bootstrap](#duration-without-bootstrap)\n- [Timespan](#timespan)\n\t- [Configuration](#configuration-1)\n- [ArrayedField](#arrayedfield)\n\t- [arrayed_text_field](#arrayed_text_field)\n\t- [arrayed_url_field](#arrayed_url_field)\n\t- [arrayed_json_field](#arrayed_json_field)\n- [Scheduler](#scheduler)\n\t- [Model](#Model)\n\t\t- [Default selection](#Default-selection)\n- [Date and Time Pickers](#date-and-time-pickers)\n- [SelectOrNew](#selectornew)\n\t- [Handling the new value](#Handling-the-new-value)\n- [Contributing](#contributing)\n\n## Requirements\n\n* Ruby 2.0+\n* Rails 5.0+\n* Twitter Bootstrap 4.0+\n\n## Dependencies\n\nThis gem will install the following gems/libraries:\n\n* [Rails Bootstrap Forms](https://github.com/bootstrap-ruby/rails-bootstrap-forms), ~\u003e 4.x\n* [$.html5data](http://markdalgleish.com/projects/jquery-html5data/), 1.0\n\n## Installation\n\nAdd it to your Gemfile:\n\n```ruby\ngem 'bootstrap_form_extensions'\n```\n\nThen:\n\n`bundle`\n\nThen require the JS in your `application.js` file:\n\n```js\n/*\n *= require bootstrap_form_extensions\n */\n```\n\nAnd require the CSS in your `application.css` file:\n\n```css\n/*\n *= require bootstrap_form_extensions\n */\n```\n\n## SubmitBar\n\nUsing all the default arguments, doing this:\n\n```erb\n\u003c%= f.submit_bar %\u003e\n```\n\ngenerates a form group, with two buttons: Save (a dropdown menu, that includes 'Save and duplicate', and 'Save and new' options), and Cancel:\n\n```html\n\u003cdiv class='form-group col-12'\u003e\n  \u003cdiv class='float-left submitbar-left'\u003e\n    \u003cdiv class='btn-group dropup submitbar-submit-group'\u003e\n      \u003cbutton type='submit' class='btn btn-primary submitbar-save'\u003eSave\u003c/button\u003e\n      \u003cbutton type='button' class='btn btn-primary dropdown-toggle dropdown-toggle-split submitbar-next-action-toggle' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'\u003e\n        \u003cspan class='sr-only'\u003eToggle Dropdown\u003c/span\u003e\n      \u003c/button\u003e\n      \u003cdiv class='dropdown-menu submitbar-next-action-menu' role='menu'\u003e\n        \u003cbutton type='submit' name='next_action' class='dropdown-item submitbar-duplicate' value='duplicate'\u003eSave and duplicate\u003c/button\u003e\n        \u003cbutton type='submit' name='next_action' class='dropdown-item submitbar-new' value='new'\u003eSave and new\u003c/button\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n    \u003ca class=\"btn btn-light submitbar-cancel\" rel=\"nofollow\" href=\"/things\"\u003eCancel\u003c/a\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n```\n\n### Configuration\n\nThe following arguments can be used to configure the submit bar:\n\n| Argument | Description | Default |\n| -------- |-------------| --------|\n| show_submit_button         | Show the Save button | true |\n| submit_button_text         | Text used in the save button | 'Save' |\n| show_submit_menu           | Show the dropdown menu on the save button | true |\n| show_submit_and_dup_button | Show a 'Save and duplicate' option in the dropdown submit menu. The 'Save' text is affected by the submit_button_text argument | true |\n| show_submit_and_new_button | Show a 'Save and new' option in the dropdown submit menu. The 'Save' text is affected by the submit_button_text argument | true |\n| show_cancel_button         | Show the Cancel button| true |\n| cancel_button_text         | Text used in the cancel button | 'Cancel' |\n| cancel_button_url          | URL used in the cancel button | If the form object is a persisted ActiveRecord instance, the url to the show action; if not, the index action. If none of these path exit, then it uses 'javascript:history.back();' |\n| extra_buttons              | An array of hashes with the definition of the extra buttons to be added between the submit and cancel buttons. The options should include at least :text and :url for the button. Anything else is passed as html options to the button | [] |\n| right_buttons              | An array of hashes with the definition of the extra buttons to be added on the right side of the submit bar. The options should include at least :text and :url for the button. Anything else is passed as html options to the button | [] |\n| partial                    | Partial template used to render the submit bar | See _Default partial_ below for details |\n\nYou can also change the default of `partial`, `show_submit_button`, `submit_button_text`, `show_submit_menu`, `show_submit_and_dup_button`, `show_submit_and_new_button`, `show_cancel_button`, `cancel_button_text`, or `back_button_text`, by invoking them on the BootstrapFormExtensions::SubmitBar, for example in an initializer file, like this:\n\n```ruby\nBootstrapFormExtensions::SubmitBar.partial = 'layouts/form_footer'\nBootstrapFormExtensions::SubmitBar.show_submit_menu = false\n```\n\n### Default partial\n\nThis is the actual code of the default partial (located in app/views/bootstrap_form_extensions/_submit_bar.html.erb):\n\n```erb\n\u003cdiv class=\"form-group col-12\"\u003e\n  \u003cdiv class='pull-left submitbar-left'\u003e\n    \u003c% if show_submit_button %\u003e\n      \u003cdiv class=\"btn-group dropup submitbar-submit-group\"\u003e\n        \u003cbutton type=\"submit\" class=\"btn btn-primary submitbar-save\"\u003e\u003c%= submit_button_text %\u003e\u003c/button\u003e\n        \u003c% if show_submit_menu %\u003e\n          \u003cbutton type=\"button\" class=\"btn btn-primary dropdown-toggle submitbar-next-action-toggle\" data-toggle=\"dropdown\"\u003e\n            \u003cspan class=\"caret\"\u003e\u003c/span\u003e\n            \u003cspan class=\"sr-only\"\u003eToggle Dropdown\u003c/span\u003e\n          \u003c/button\u003e\n          \u003cul class=\"dropdown-menu submitbar-next-action-menu\" role=\"menu\"\u003e\n            \u003c% if show_submit_and_dup_button %\u003e\n              \u003cli\u003e\u003cbutton type=\"submit\" name=\"next_action\" class=\"btn-link submitbar-duplicate\" value=\"duplicate\"\u003e\u003c%= submit_button_text %\u003e and duplicate\u003c/button\u003e\u003c/li\u003e\n            \u003c% end %\u003e\n            \u003c% if show_submit_and_new_button %\u003e\n              \u003cli\u003e\u003cbutton type=\"submit\" name=\"next_action\" class=\"btn-link submitbar-new\" value=\"new\"\u003e\u003c%= submit_button_text %\u003e and new\u003c/button\u003e\u003c/li\u003e\n            \u003c% end %\u003e\n          \u003c/ul\u003e\n        \u003c% end %\u003e\n      \u003c/div\u003e\n    \u003c% end %\u003e\n    \u003c% extra_buttons.each do |text:, url:, options:| %\u003e\n      \u003c%= link_to text, url, options %\u003e\n    \u003c% end %\u003e\n    \u003c% if show_cancel_button %\u003e\n      \u003c%= link_to cancel_button_text, cancel_button_url, class: \"btn btn-light submitbar-cancel\", rel: \"nofollow\" %\u003e\n    \u003c% end %\u003e\n  \u003c/div\u003e\n  \u003c% if right_buttons.any? %\u003e\n    \u003cdiv class='pull-right submitbar-right'\u003e\n      \u003c% right_buttons.each do |text:, url:, options:| %\u003e\n        \u003c%= link_to text, url, options %\u003e\n      \u003c% end %\u003e\n    \u003c/div\u003e\n  \u003c% end %\u003e\n\u003c/div\u003e\n```\n\nYou can use it as a template to create your own partial(s).\n\n## Duration\n\nHaving, for example, a column `duration_in_seconds` (a float column, to handle milliseconds), doing this:\n\n```erb\n\u003c%= f.duration :duration_in_seconds %\u003e\n```\n\ngenerates this html:\n\n```html\n\u003cdiv class=\"form-group duration-group row\" data-duration=\"true\"\u003e\n  \u003clabel class=\"col-form-label col-2\" for=\"thing_duration_in_seconds\"\u003eDuration in seconds\u003c/label\u003e\n  \u003cdiv class=\"col-10 form-inline\"\u003e\n    \u003cinput class=\"duration-seconds\" id=\"thing_duration_in_seconds\" name=\"thing[duration_in_seconds]\" type=\"hidden\" value=\"0.000\"\u003e\n    \u003cinput class=\"form-control hours\" id=\"thing_hours\" min=\"0\" name=\"thing[hours]\" type=\"number\" value=\"0\"\u003e\n    :\n    \u003cinput class=\"form-control minutes\" id=\"thing_minutes\" max=\"59\" min=\"0\" name=\"thing[minutes]\" type=\"number\" value=\"0\"\u003e\n    :\n    \u003cinput class=\"form-control seconds\" id=\"thing_seconds\" max=\"59\" min=\"0\" name=\"thing[seconds]\" type=\"number\" value=\"0\"\u003e\n    .\n    \u003cinput class=\"form-control milliseconds\" id=\"thing_milliseconds\" max=\"999\" min=\"0\" name=\"thing[milliseconds]\" type=\"number\" value=\"0\"\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n```\n\nIt accepts any option you'd pass to a form_group.\n\n### Duration without bootstrap\n\nThere is a version of this control that doesn't apply all bootstrap styling:\n\n```erb\n\u003c%= f.duration_without_bootstrap :duration_in_seconds %\u003e\n```\n\ngenerates this html:\n\n```html\n\u003cdiv class=\"duration-group\" data-duration=\"true\"\u003e\n  \u003cinput class=\"duration-seconds\" id=\"thing_duration_in_seconds\" name=\"thing[duration_in_seconds]\" type=\"hidden\" value=\"0\"\u003e\n  \u003cinput class=\"hours\" id=\"thing_hours\" min=\"0\" name=\"thing[hours]\" type=\"number\" value=\"0\"\u003e\n  :\n  \u003cinput class=\"minutes\" id=\"thing_minutes\" max=\"59\" min=\"0\" name=\"thing[minutes]\" type=\"number\" value=\"0\"\u003e\n  :\n  \u003cinput class=\"seconds\" id=\"thing_seconds\" max=\"59\" min=\"0\" name=\"thing[seconds]\" type=\"number\" value=\"0\"\u003e\n  .\n  \u003cinput class=\"milliseconds\" id=\"thing_milliseconds\" max=\"999\" min=\"0\" name=\"thing[milliseconds]\" type=\"number\" value=\"0\"\u003e\n\u003c/div\u003e\n```\n\nIf you still want to use the bootstrap styling, but not the form formatting (for instance, when you need to include this control in an inline form, or inside another element), you can customize like this:\n\n```erb\n\u003c%= f.duration_without_bootstrap :duration_in_seconds, class: 'form-control', wrapper_class: 'form-inline' %\u003e\n```\n\n## Timespan\n\nHaving, for example, a column `duration_in_seconds`, doing this:\n\n```erb\n\u003c%= f.timespan :duration_in_seconds %\u003e\n```\n\ngenerates this html:\n\n```html\n\u003cspan data-timespan=\"true\"\u003e\n  \u003cinput class=\"timespan-seconds\" type=\"hidden\" value=\"3600\" name=\"thing[duration_in_seconds]\" id=\"thing_duration_in_seconds\" /\u003e\n  \u003cdiv class=\"form-group row\"\u003e\n    \u003cinput type=\"text\" name=\"duration_quantity\" id=\"duration_quantity\" value=\"1\" size=\"5\" class=\"form-control timespan-quantity\" /\u003e\n  \u003c/div\u003e\n  \u0026nbsp;\n  \u003cdiv class=\"form-group row\"\u003e\n    \u003cselect name=\"duration_unit\" id=\"duration_unit\" class=\"form-control timespan-unit\"\u003e\n      \u003coption selected=\"selected\" value=\"1\"\u003eseconds\u003c/option\u003e\n      \u003coption value=\"60\"\u003eminutes\u003c/option\u003e\n      \u003coption value=\"3600\"\u003ehours\u003c/option\u003e\n      \u003coption value=\"86400\"\u003edays\u003c/option\u003e\n      \u003coption value=\"604800\"\u003eweeks\u003c/option\u003e\n      \u003coption value=\"18144000\"\u003emonths\u003c/option\u003e\n    \u003c/select\u003e\n  \u003c/div\u003e\n\u003c/span\u003e\n```\n\n### Configuration\n\nThe following arguments can be used to configure the timespan:\n\n| Argument | Description | Default |\n| -------- |-------------| --------|\n| units            | The list of units that will be displayed       | [ :seconds, :minutes, :hours, :days, :weeks, :months ] |\n| quantity_options | html options to be added to the quantity input | {} |\n| unit_options     | html options to be added to the unit select    | {} |\n\nYou can also change the default of `units` by invoking it on the BootstrapFormExtensions::Timespan, for example in an initializer file, like this:\n\n```ruby\nBootstrapFormExtensions::Timespan.units = [ :hours, :days ]\n```\n\n## ArrayedField\n\nArrayedField provides three helpers:\n\n### arrayed_text_field\n\nGiven a column that holds an array of texts, this helper adds a multiple line text inputs:\n\n```erb\n\u003c%= f.arrayed_text_field :lists %\u003e\n```\n\nIt accepts any option you'd pass to a form_group. If the column provided doesn't exist, or is not an array, it assumes an empty array as the value.\n\n### arrayed_url_field\n\nGiven a column that holds an array of URLs, this helper adds a multiple line url inputs:\n\n```erb\n\u003c%= f.arrayed_url_field :urls %\u003e\n```\n\nIt accepts any option you'd pass to a form_group. If the column provided doesn't exist, or is not an array, it assumes an empty array as the value.\n\n### arrayed_json_field\n\nGiven a column that holds an array of hashes, this helper adds a multiple line, multiple field, text/select inputs:\n\n```erb\n\u003c%= f.arrayed_json_field :variables, [ :name, :value ] %\u003e\n```\n\nThe generated html contains multiple lines like this:\n\n```html\n\u003cdiv class=\"col-2\"\u003e\n  \u003cinput type=\"text\" name=\"thing[variables][][name]\" class=\"form-control\" placeholder=\"name\" /\u003e\n\u003c/div\u003e\n\u003cdiv class=\"col-2\"\u003e\n  \u003cinput type=\"text\" name=\"thing[variables][][value]\" class=\"form-control\" placeholder=\"value\" /\u003e\n\u003c/div\u003e\n```\n\nThe list of fields in the hash can be customized further:\n\n```erb\n\u003c%= f.arrayed_json_field :variables, [ { name: { type: :select, options: [ [ \"One\", \"var1\" ], [ \"Two\", \"var2\" ] ] } }, :value ] %\u003e\n```\n\n`type` can be `:text` or `:select`.\n\nThe generated html for each element of the array would look something like this:\n\n```html\n\u003cdiv class=\"col-2\"\u003e\n  \u003cselect class=\"form-control\"\u003e\n    \u003coption value=\"var1\"\u003eOne\u003c/option\u003e\n    \u003coption value=\"var2\"\u003eTwo\u003c/option\u003e\n  \u003c/select\u003e\n\u003c/div\u003e\n\u003cdiv class=\"col-2\"\u003e\n  \u003cinput class=\"form-control\" name=\"thing[variables][][value]\" placeholder=\"value\" type=\"text\"\u003e\n\u003c/div\u003e\n```\n\nIt accepts any option you'd pass to a form_group. If the column provided doesn't exist, or is not an array, it assumes an empty array as the value.\n\n## Scheduler\n\nThis widget creates a grid of days and hours to choose a schedule. Called like this:\n\n```erb\n\u003c%= f.scheduler :schedule %\u003e\n```\n\ngenerates this:\n\n![scheduler - badge](https://raw.githubusercontent.com/jdugarte/rails-bootstrap-form-extensions/gh-pages/images/scheduler%20-%20badge%20-%20partial%20selection.png)\n\nThis grid reflects the schedule selected. Clicking on the grid brings up the schedule editor:\n\n![scheduler - editor](https://raw.githubusercontent.com/jdugarte/rails-bootstrap-form-extensions/gh-pages/images/scheduler%20-%20editor%20-%20partial%20selection.png)\n\nThe days and hours headers are clickable, as well as each cell, to allow any custom selection.\n\n`scheduler` accepts the same arguments than bootstrap form's `form_group`: a method for the value, and options for the form group.\n\n### Model\n\nThis control expects the attribute to be serialized like this:\n\n```ruby\n# Migration:\n\nclass AddSchedulerField \u003c ActiveRecord::Migration\n  def change\n    add_column :things, :schedule, :text\n  end\nend\n\n# Model\n\nclass Thing \u003c ActiveRecord::Base\n  ...\n  serialize :schedule, BootstrapFormExtensions::Scheduler.serializer\n  ...\nend\n```\n\nThis will serialize the column to yaml. If you're using an array column (e.g. PostgreSQL), you could do:\n\n```ruby\n# Migration:\n\nclass AddSchedulerField \u003c ActiveRecord::Migration\n  def change\n    add_column :things, :schedule, :text, array: true, default: []\n  end\nend\n\n# Model\n\nclass Thing \u003c ActiveRecord::Base\n  ...\n  serialize :schedule, BootstrapFormExtensions::Scheduler.serializer to: :array\n  ...\nend\n```\n\n#### Default selection\n\nEach hour in the schedule grid is selected by default:\n\n```ruby\n\u003e thing = Thing.new schedule: []\n\u003e thing.schedule\n=\u003e [[true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true], ...]\n```\n\nYou can change this default in the model:\n\n```ruby\nclass Thing \u003c ActiveRecord::Base\n  ...\n  serialize :schedule, BootstrapFormExtensions::Scheduler.serializer default_selection: false\n  ...\nend\n```\n\nThis would result in:\n\n```ruby\n\u003e thing = Thing.new schedule: []\n\u003e thing.schedule\n=\u003e [[false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], ...]\n```\n\n## Date and Time Pickers\n\nDate and Time Pickers have been deprecated since bootstrap form already offers good replacements for them.\n\n## SelectOrNew\n\nThis helpers creates a select tag with an extra \"New...\" option at the end, that allows the user to input a new item. For instance:\n\n```erb\n\u003c%= f.select_or_new :category, [ [ 'One', 1 ], [ 'Two', 2 ] ] %\u003e\n```\n\ngenerates this html:\n\n```html\n\u003cdiv class=\"form-group row\" data-select-or-new=\"true\"\u003e\n  \u003clabel class=\"col-form-label col-2\" for=\"thing_category\"\u003eCategory\u003c/label\u003e\n  \u003cdiv class=\"col-10\"\u003e\n    \u003cselect class=\"form-control\" name=\"thing[category]\" id=\"thing_category\"\u003e\n      \u003coption value=\"\"\u003ePlease select\u003c/option\u003e\n      \u003coption value=\"1\"\u003eOne\u003c/option\u003e\n      \u003coption value=\"2\"\u003eTwo\u003c/option\u003e\n      \u003coption value=\"0\"\u003eNew...\u003c/option\u003e\n    \u003c/select\u003e\n    \u003cdiv class=\"input-group\" style=\"display: none;\"\u003e\n      \u003cinput type=\"text\" name=\"thing[new_category]\" id=\"thing_new_category\" value=\"New Category\" class=\"form-control\" placeholder=\"New...\"\u003e\n      \u003cdiv class=\"input-group-append select-or-new-cancel\"\u003e\n        \u003cbutton class=\"btn btn-outline-danger\" type=\"button\"\u003e×\u003c/button\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n```\n\nInitially, the control looks like a regular select tag:\n\n![select_or_new - select](https://raw.githubusercontent.com/jdugarte/rails-bootstrap-form-extensions/2ee06731be906d44edf6104a44e5db9d3a7790b8/images/select_or_new%20-%20select.png)\n\nWhen \"New...\" is selected, it turns to:\n\n![select_or_new - input](https://raw.githubusercontent.com/jdugarte/rails-bootstrap-form-extensions/2ee06731be906d44edf6104a44e5db9d3a7790b8/images/select_or_new%20-%20input.png)\n\nTo go back to the select (canceling the new input), click on the cancel button (the red X).\n\nThe helper accepts the same parameters as [Rails' select helper](http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select), plus any option you'd pass to a form_group.\n\nIf any of the choices you provided is selected, the appropriate value will be set in the filed (category_id, in the previous example). If \"New...\" is selected, the id will be set to '0', and a field called \"new\\__field_\" will be added (in the previous example that would be: category_id = '0', new_category = 'New Category').\n\n### Handling the new value\n\nYou could have something like this in the controller:\n\n```ruby\nclass ThingsController \u003c ApplicationController\n\n  ...\n\n  def create\n    @thing = Thing.build thing_params\n    @thing.save_with_category\n    respond_with @thing\n  end\n\n  def update\n    @thing = Thing.find(params[:id])\n    @thing.assign_attributes thing_params\n    @thing.save_with_category\n    respond_with @thing\n  end\n\n  private\n\n  def thing_params\n    params.require(:thing).permit :name, :category_id, :new_category\n  end\n\n  ...\n\nend\n```\n\nAnd then in the model:\n\n```ruby\nclass Thing \u003c ActiveRecord::Base\n\n  belongs_to :category\n\n  validates :name, :category_id, presence: true\n  validate :new_category_presence\n\n  attr_accessor :new_category\n\n  def save_with_category\n    return false unless valid?\n    transaction { add_category_if_new \u0026\u0026 save }\n  end\n\n  private\n\n  def add_category_if_new\n    return true unless category_id == 0\n\n    category = Category.build name: new_category\n    if category.save\n      self.category, self.new_category = category, ''\n      return true\n    end\n\n    errors.add :category_id, category.errors.full_messages\n    return false\n  end\n\n  def new_category_presence\n    return true unless category_id == 0\n\n    if new_category.blank?\n      errors.add :category_id, \"can't be blank\"\n      return false\n    end\n  end\n\nend\n```\n\n## Contributing\n\nHere's a quick guide for contributing:\n\n1. Fork the repo.\n\n2. Run the existing test suite:\n\n```\n$ bundle exec rake -f test/dummy/Rakefile db:create db:migrate RAILS_ENV=test\n$ bundle exec rake\n$ bundle exec rake jasmine:ci\n```\n\n3. Add tests for your change.\n\n4. Add your changes and make your test(s) pass.\n\n5. Update the README if necessary.\n\n6. Add a line to the CHANGELOG for your bug fix or feature.\n\n7. Push to your fork and submit a pull request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdugarte%2Frails-bootstrap-form-extensions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdugarte%2Frails-bootstrap-form-extensions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdugarte%2Frails-bootstrap-form-extensions/lists"}