{"title":"Form Builder","description":"","section":"guides/views","version":"v1.5","path":"guides/views/form-builder","canonical_url":"https://amberframework.org/docs/v1.5/guides/views/form-builder","markdown_url":"https://amberframework.org/docs/v1.5/guides/views/form-builder.md","inherited":true,"content_markdown":"# Form Builder\n\nYou may find yourself looking for a more advanced way to build your HTML forms that is both simple and productive. For this we recommend the optional shard [FormBuilder.cr](https://github.com/westonganger/form_builder.cr)\n\n## Features of FormBuilder.cr\n\n- Easily generate HTML markup for forms, labels, inputs, and help text\n- Support for error messages for your validations\n- Creates markup for the following UI libraries out of the box such as Bootstrap (v2-v4), Bulma, Foundation, Materialize, Milligram & Semantic UI\n- Custom theme support\n\n## Installation\n\nBecause this is an optional addon you must install and require it in your Amber project.\n\nAdd this to your application's `shard.yml` file:\n\n```yaml\ndependencies:\n  form_builder:\n    github: westonganger/form_builder.cr\n```\n\nThen require it within the `config/application.cr` file:\n\n```crystal\nrequire \"form_builder\"\n```\n\n## Usage\n\nThe following field types are supported:\n\n- `:checkbox`\n- `:file`\n- `:hidden`\n- `:password`\n- `:radio`\n- `:select`\n- `:text`\n- `:textarea`\n\n## FormBuilder in View Templates (Example in Slang)\n\n```crystal\n== FormBuilder.form(theme: :bootstrap_4_vertical, action: \"/products\", method: :post, form_html: {style: \"margin-top: 20px;\", \"data-foo\" => \"bar\"}) do |f|\n  == csrf_tag\n  \n  .row.main-examples\n    .col-sm-6\n      ### -- Field Options\n      ### type : (String | Symbol)\n      ### name : (String | Symbol)?\n      ### label : (String | Bool)? = true\n      ### help_text : String?\n\n      ### value : (String | Symbol)?\n      ### -- Note: The `input_html[\"value\"]` option will take precedence over the :value option (except for `type: :textarea/:select`)\n\n      ### errors : (Array(String) | String)?\n      ### -- Note: Array(String) generates a list of help text elements. If you have an Array of errors and you only want a single help text element, then join your errors array to a String\n\n      ### -- For the following Hash options, String keys will take precedence over any Symbol keys\n      ### input_html : (Hash | NamedTuple)? ### contains attributes to be added to the input/field\n      ### label_html : (Hash | NamedTuple)? ### contains attributes to be added to the label\n      ### wrapper_html : (Hash | NamedTuple)? ### contains attributes to be added to the outer wrapper for the label and input\n      ### help_text_html : (Hash | NamedTuple)? ### contains attributes to be added to the help text container\n      ### error_html : (Hash | NamedTuple)? ### contains attributes to be added to the error container(s) \n \n      == f.field name: \"product[name]\", label: \"Name\", type: :text, errors: product_errors[\"name\"]\n\n      == f.field name: \"product[description]\", label: \"Description\", type: :textarea, input_html: {class: \"foobar\"}, wrapper_html: {style: \"margin-top: 10px\"}, label_html: {style: \"color: red;\"}\n\n      == f.field name: \"product[file]\", type: :file, help_text: \"Must be a PDF\", help_text_html: {style: \"color: blue;\"}\n\n    .col-sm-6\n      == f.field name: \"product[available]\", type: :checkbox, label: \"In Stock?\"\n\n      == f.field name: \"product[class]\", type: :radio, label: false\n\n      == f.field name: \"product[secret]\", type: :hidden, value: \"foobar\"\n\n  .row.select-example\n    ### -- Additional Options for `type: :select`\n    ### collection : (Hash | NamedTuple) = {\n    ###   options : (Array(String) | Array(String | Array(String)) | String) ### Required, Note: The non-Array String type is for passing in a pre-built html options string\n    ###   selected : (String | Array(String))?\n    ###   disabled : (String | Array(String))?\n    ###   include_blank : (String | Bool)?\n    ### }\n    ### -- Note: String keys will take precedence over any Symbol keys\n\n    ### -- When passing a nested array to collection[:options] the Option pairs are defined as: [required_value, optional_label]\n    - opts = [[\"A\", \"Type A\"], [\"B\" \"Type B\"], [\"C\", \"Type C\"], \"Other\"]\n\n    == f.field name: \"product[type]\", label: \"Type\", type: :select, collection: {options: opts, selected: [\"B\"], disabled: [\"C\"]}\n```\n\n## FormBuilder in Plain Crystal Code\n\nWhen using the `FormBuilder.form` method in plain Crystal code, the `<<` syntax is required to add the generated field HTML to the form HTML string\n\n```crystal\nform_html_str = FormBuilder.form(theme: :bootstrap_4_vertical, action: \"/products\", method: :post, form_html: {style: \"margin-top: 20px;\", \"data-foo\" => \"bar\"}) do |f|\n  f << csrf_tag\n  f << f.field(name: \"name\", type: :text, label: \"Name\")\n  f << f.field(name: \"sku\", type: :text, label: \"SKU\")\n  f << \"<strong>Hello World</strong>\"\nend\n```\n\nOR you can use the lower level `String.build` instead:\n\n```crystal\nform_html_str = String.build do |str|\n  str << FormBuilder.form(theme: :bootstrap_4_vertical, action: \"/products\", method: :post, form_html: {style: \"margin-top: 20px;\", \"data-foo\" => \"bar\"}) do |f|\n    str << csrf_tag\n    str << f.field(name: \"name\", type: :text, label: \"Name\")\n    str << f.field(name: \"sku\", type: :text, label: \"SKU\")\n    str << \"<strong>Hello World</strong>\"\n  end\nend\n```\n\n## FormBuilder without a Form\n\n```crystal\n- f = FormBuilder::Builder.new(theme: :bootstrap_4_vertical)\n\n== f.field name: \"name\", type: :text, label: \"Name\"\n== f.field name: \"sku\", type: :text, label: \"SKU\"\n```\n\n## Error Handling\n\nThe form builder is capable of handling error messages too. If the `:errors` argument is provided it will generate the appropriate error help text element(s) next to the field.\n\n```crystal\n== FormBuilder.form(theme: :bootstrap_4_vertical) do |f|\n  == csrf_tag\n\n  == f.field name: \"name\", type: :text, label: \"Name\", errors: \"cannot be blank\"\n  == f.field name: \"sku\", type: :text, label: \"SKU\", errors: [\"must be unique\", \"incorrect SKU format\")\n```\n\n## Theme List\n\nOut of the box Form Builder can generate HTML markup for a variety of popular UI libraries. Custom Themes are also supported, please see the [FormBuilder.cr README](https://github.com/westonganger/form_builder.cr) for details.\n\nThe current list of built-in themes are as follows.\n\n- Bootstrap 4 \n  * `theme: :bootstrap_4_vertical`\n  * `theme: :bootstrap_4_inline`\n  * `theme: :bootstrap_4_horizontal` or `theme: FormBuilder::Themes::Bootstrap4Horizontal.new(column_classes: [\"col-sm-3\",\"col-sm-9\"])`\n- Bootstrap 3\n  * `theme: :bootstrap_3_vertical`\n  * `theme: :bootstrap_3_inline`\n  * `theme: :bootstrap_3_horizontal` or `theme: FormBuilder::Themes::Bootstrap3Horizontal.new(column_classes: [\"col-sm-3\",\"col-sm-9\"])`\n- Bootstrap 2\n  * `theme: :bootstrap_2_vertical`\n  * `theme: :bootstrap_2_inline`\n  * `theme: :bootstrap_2_horizontal`\n- Bulma\n  * `theme: :bulma_vertical`\n  * `theme: :bulma_horizontal`\n- Foundation\n  * `theme: :foundation`\n- Materialize\n  * `theme: :materialize`\n- Milligram\n  * `theme: :milligram`\n- Semantic UI\n  * `theme: :semantic_ui_vertical`\n  * `theme: :semantic_ui_inline`\n- None (Default)\n  * `theme: :default`\n  * `theme: nil`\n  * or simply do not provide a `:theme` argument\n\nFor further information please see the official [FormBuilder.cr README](https://github.com/westonganger/form_builder.cr)"}