{"id":13879227,"url":"https://github.com/kuroda/vue-rails-form-builder","last_synced_at":"2026-04-06T04:06:25.766Z","repository":{"id":56897681,"uuid":"87320696","full_name":"kuroda/vue-rails-form-builder","owner":"kuroda","description":"A custom Rails form builder for Vue.js","archived":false,"fork":false,"pushed_at":"2021-07-20T04:51:52.000Z","size":27,"stargazers_count":80,"open_issues_count":3,"forks_count":9,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-01-01T10:32:48.790Z","etag":null,"topics":["form-builder","rails","ruby","vuejs"],"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/kuroda.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":"2017-04-05T14:41:37.000Z","updated_at":"2024-05-26T00:54:41.000Z","dependencies_parsed_at":"2022-08-21T02:20:17.752Z","dependency_job_id":null,"html_url":"https://github.com/kuroda/vue-rails-form-builder","commit_stats":null,"previous_names":["kuroda/vue-form-for"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuroda%2Fvue-rails-form-builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuroda%2Fvue-rails-form-builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuroda%2Fvue-rails-form-builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuroda%2Fvue-rails-form-builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kuroda","download_url":"https://codeload.github.com/kuroda/vue-rails-form-builder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":232548659,"owners_count":18540144,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["form-builder","rails","ruby","vuejs"],"created_at":"2024-08-06T08:02:14.202Z","updated_at":"2026-04-06T04:06:25.734Z","avatar_url":"https://github.com/kuroda.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"vue-rails-form-builder\n======================\n\n[![Gem Version](https://badge.fury.io/rb/vue-rails-form-builder.svg)](https://badge.fury.io/rb/vue-rails-form-builder)\n\nA custom Rails form builder for Vue.js\n\nSynopsis\n--------\n\n```erb\n\u003c%= vue_form_for User.new do |f| %\u003e\n  \u003c%= f.text_field :name %\u003e\n\u003c% end %\u003e\n```\n\n```html\n\u003cform ...\u003e\n  ...\n  \u003cinput v-model=\"user.name\" type=\"text\" name=\"user[name]\" ... /\u003e\n\u003c/form\u003e\n```\n\nInstallation\n------------\n\nAdd the following line to `Gemfile`:\n\n```ruby\ngem \"vue-rails-form-builder\"\n```\n\nRun `bundle install` on the terminal.\n\nUsage\n-----\n\n```erb\n\u003c%= vue_form_for User.new do |f| %\u003e\n  \u003c%= f.text_field :name %\u003e\n  \u003c%= f.submit \"Create\" %\u003e\n\u003c% end %\u003e\n```\n\nThe above ERB template will be rendered into the following HTML fragment:\n\n```html\n\u003cform class=\"new_user\" id=\"new_user\" action=\"/users\" accept-charset=\"UTF-8\" method=\"post\"\u003e\n  \u003cinput name=\"utf8\" type=\"hidden\" value=\"\u0026#x2713;\" /\u003e\n  \u003cinput type=\"hidden\" name=\"authenticity_token\" value=\"...\" /\u003e\n  \u003cinput v-model=\"user.name\" type=\"text\" name=\"user[name]\" id=\"user_name\" /\u003e\n  \u003cinput type=\"submit\" name=\"commit\" value=\"Create\" /\u003e\n\u003c/form\u003e\n```\n\nNote that the third `\u003cinput\u003e` element has a `v-model` attriubte, which can be\ninterpreted by Vue.js as the _directive_ to create two-way data bindings between\nform fields and component's data.\n\nIf you are using the [Webpacker](https://github.com/rails/webpacker),\ncreate `app/javascript/packs/new_user_form.js` with following code:\n\n```javascript\nimport Vue from 'vue/dist/vue.esm'\n\ndocument.addEventListener(\"DOMContentLoaded\", () =\u003e {\n  const NewUserForm = new Vue({\n    el: \"#new_user\",\n    data: {\n      user: {\n        name: \"\"\n      }\n    }\n  })\n})\n```\n\nAdd this line to the ERB template:\n\n```erb\n\u003c%= javascript_pack_tag \"new_user_form\" %\u003e\n```\n\nThen, you can get the value of `user[name]` field by the `user.name`.\n\nIf you use Rails 5.1 or above, you can also use `vue_form_with`:\n\n```erb\n\u003c%= vue_form_with model: User.new do |f| %\u003e\n  \u003c%= f.text_field :name %\u003e\n  \u003c%= f.submit \"Create\" %\u003e\n\u003c% end %\u003e\n```\n\nDemo App\n--------\n\nVisit [vue-rails-form-builder-demo](https://github.com/kuroda/vue-rails-form-builder-demo)\nfor a working Rails demo application using the `vue-rails-form-builder`.\n\nOptions\n-------\n\nTo `vue_form_for` and `vue_form_with` methods you can provide the same options\nas `form_for` and `form_with`.\n\nThere is a special option:\n\n* `:vue_scope` - The prefix used to the input field names within the Vue\n  component.\n\nTag Helper\n----------\n\nThis gem provides two additional helper methods: `vue_tag` and `vue_content_tag`.\n\nBasically, they behave like `tag` and `content_tag` helpers of Action Views.\nBut, they interpret the *HTML options* in a different way as explained below.\n\n### The `:bind` option\n\nIf the *HTML options* have a `:bind` key and its value is a hash,\nthey get transformed into the Vue.js `v-bind` directives.\n\nIn the example below, these two lines have the same result:\n\n```erb\n\u003c%= vue_content_tag(:span, \"Hello\", bind: { style: \"{ color: textColor }\" }) %\u003e\n\u003c%= vue_content_tag(:span, \"Hello\", \"v-bind:style\" =\u003e \"{ color: textColor }\" }) %\u003e\n```\n\nNote that you should use the latter style if you want to specify *modifiers*\nto the `v-bind` directives. For example:\n\n```erb\n\u003c%= vue_content_tag(:span, \"Hello\", \"v-bind:text-content.prop\" =\u003e \"message\" }) %\u003e\n```\n\n### The `:on` option\n\nIf the *HTML options* have a `:on` key and its value is a hash,\nthey get transformed into the Vue.js `v-on` directives.\n\nIn the example below, these two lines have the same result:\n\n```erb\n\u003c%= vue_content_tag(:span, \"Hello\", on: { click: \"doThis\" }) %\u003e\n\u003c%= vue_content_tag(:span, \"Hello\", \"v-on:click\" =\u003e \"doThis\" }) %\u003e\n```\n\nNote that you should use the latter style if you want to specify *modifiers*\nto the `v-on` directives. For example:\n\n```erb\n\u003c%= vue_content_tag(:span, \"Hello\", \"v-on:click.once\" =\u003e \"doThis\" }) %\u003e\n\u003c%= vue_content_tag(:button, \"Hello\", \"v-on:click.prevent\" =\u003e \"doThis\" }) %\u003e\n```\n\n### Boolean attributes\n\nIf the *HTML options* have a string value (not a boolean value)\nfor `checked`, `disabled`, `multiple`, `readonly` or `selected` key,\nthe key gets transformed by adding `v-bind:` to its head.\n\nIn the example below, these two lines have the same result:\n\n```erb\n\u003c%= vue_content_tag(:button, \"Click me!\", disabled: \"!clickable\") %\u003e\n\u003c%= vue_content_tag(:button, \"Click me!\", \"v-bind:disabled\" =\u003e \"!clickable\") %\u003e\n```\n\nIf you want to add a normal attribute without `v-bind:` prefix,\nspecify `true` (boolean) to these keys:\n\n```erb\n\u003c%= vue_content_tag(:button, \"Click me!\", disabled: true) %\u003e\n```\n\nThis line produces the following HTML fragment:\n\n```html\n\u003cbutton disabled=\"disabled\"\u003eClick me!\u003c/button\u003e\n```\n\n\n### Vue.js directives\n\nIf the *HTML options* have one or more of the following keys\n\n\u003e `text`, `html`, `show`, `if`, `else`, `else_if`, `for`, `model`, `pre`, `cloak`, `once`\n\nthen, these keys get transformed by adding `v-` to their head.\n\nIn the example below, these two lines have the same result:\n\n```erb\n\u003c%= vue_tag(:hr, if: \"itemsPresent\") %\u003e\n\u003c%= vue_tag(:hr, \"v-if\" =\u003e \"itemsPresent\") %\u003e\n```\n\nNote that the `:else_if` key is transformed into the `v-else-if` directive:\n\n```erb\n\u003c%= vue_tag(:hr, else_if: \"itemsPresent\") %\u003e\n\u003c%= vue_tag(:hr, \"v-else-if\" =\u003e \"itemsPresent\") %\u003e\n```\n\n### Extensions to the form building helpers\n\nWhen you build HTML forms using `vue_form_for`,\nthe form building helpers, such as `text_field`, `check_box`, etc.,\nhave these additional behavior.\n\nExample:\n\n```erb\n\u003c%= vue_form_for User.new do |f| %\u003e\n  \u003c%= f.text_field :name, model: \"userName\" %\u003e\n  \u003clabel\u003e\n    \u003c%= f.check_box :administrator, on: { click: \"doThis\" } %\u003e Administrator\n  \u003c/label\u003e\n  \u003c%= f.submit \"Create\", disabled: \"!submittable\" %\u003e\n\u003c% end %\u003e\n```\n\nThe `vue_prefix` method of the Form Builder\n-------------------------------------------\n\nWhen you build HTML forms using `vue_form_for`, the form builder has the\n`vue_prefix` method that returns the *prefix string* to the Vue.js property names.\n\nSee the following code:\n\n```erb\n\u003c%= vue_form_for User.new do |f| %\u003e\n  \u003c%= f.text_field :name %\u003e\n  \u003c%= f.submit \"Create\", disabled: \"user.name === ''\" %\u003e\n\u003c% end %\u003e\n```\n\nThe `vue_prefix` method of the form builder (`f`) returns the string `\"user\"`\nso that you can rewrite the third line of the example above like this:\n\n```erb\n  \u003c%= f.submit \"Create\", disabled: \"#{f.vue_prefix}.name === ''\" %\u003e\n```\n\nThis method is convenient especially when the form has nested attributes:\n\n```erb\n\u003c%= vue_form_for @user do |f| %\u003e\n  \u003c%= f.text_field :name %\u003e\n  \u003c%= f.fields_for :emails do |g| %\u003e\n    \u003c%= g.text_field :address,\n      disabled: \"user.emails_attributes[#{g.index}]._destroy\" %\u003e\n    \u003c%= g.check_box :_destroy if g.object.persisted? %\u003e\n  \u003c% end %\u003e\n  \u003c%= f.submit \"Create\", disabled: \"#{f.vue_prefix}.name === ''\" %\u003e\n\u003c% end %\u003e\n```\n\nUsing the `vue_prefix` method, you can rewrite the fifth line more concisely:\n\n```erb\n      disabled: g.vue_prefix + \"._destroy\" %\u003e\n```\n\nData Initialization\n-------------------\n\nAs the official Vue.js document says:\n\n\u003e `v-model` will ignore the initial `value`, `checked` or `selected` attributes\n\u003e found on any form elements.\n\u003e (https://vuejs.org/v2/guide/forms.html)\n\nBecause of this, all form controls get reset after the Vue component is mounted.\n\nHowever, you can use\n[vue-data-scooper](https://github.com/kuroda/vue-data-scooper) plugin\nin order to keep the original state of the form.\n\nLicense\n-------\n\nThe `vue-rails-form-builder` is distributed under the MIT license. ([MIT-LICENSE](https://github.com/kuroda/vue-rails-form-builder/blob/master/MIT-LICENSE))\n\nAuthor\n------\n\nTsutomu Kuroda (t-kuroda@oiax.jp)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkuroda%2Fvue-rails-form-builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkuroda%2Fvue-rails-form-builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkuroda%2Fvue-rails-form-builder/lists"}