フォーム要素をまるっと Vue.js で管理したいとき v-model を指定すると初期値が Vue.js 側の値で上書きされて、フォームにもともと指定してあった value の値が無視されてしまう問題にいまごろ直面しました。
もともと Vue.js 1系のころは v-model で指定した値にフォームの初期値が入っていたそうなのですが2系からは入らなくなったようです。
そこで先人が考え出したアイデアがこちらです。とても興味深いです。
Railsのフォームビルダーで生成したform要素をVueコンポーネント化する
https://qiita.com/kuroda@github/items/940338b5f6f46da2c5f1
記事を拝見する前、私はひとつひとつの input に ref 属性をつけて this.$refs.xxx
として値を取得する方法を試みていたのですが querySelector という手があったかと感心しました。さらには完全にライブラリ化&ブラックボックス化しており、同じコードは二度と書かねえという心意気を感じます。scaffold で生成したフォームを Vue.js で管理できるようにする目的であればできてます。
ただ、 Vue.js でフォームを管理できるようになると、いろいろやりたくなってくるんです(笑) いろいろやるにはデータは全部欲しいわけです。フォームに無い値も使いたくなるんです。
上の方法ではデータは HTML のタグ経由なので、データを渡すために input タグを定義するという変な感じになってきます。そうなるともう最初から Vue.js にデータを全部まるっと渡しとけばいいんじゃねってことになります。で、これに行きつきました。
import Vue from "vue/dist/vue.esm"
window.UserForm = Vue.extend({
data() {
return {
user: this.$options.user_attributes,
}
},
})
# app
= form.text_field(:foo, "v-model": "user.foo")
= form.text_field(:bar, "v-model": "user.bar")
javascript:
new UserForm({user_attributes: #{form.object.to_json.html_safe}}).$mount("#app")
Vue.js のクラスは一箇所で定義して、それを使うときに form.object を全部渡してインスタンス生成します。当初は propsData で渡したりしていましたが、それはテスト用らしいので、普通に引数で渡して $options で参照する方法にしました。
けっこうシンプルでいいかなと思うんですが、こういうのどうなんでしょう?