はじめに
入力パーツがたくさんある場合、templateにバラで書くと長くなるのでv-forで回して生成したくなりますが、そこでv-modelをループ変数に基づいて動的に作ろうとすると、やりたいようにできないことがあります。
できる方法があればぜひ教えて下さい!
うまくいくケース
このようにv-modelの参照先が階層化されていてトップが固定のliteralで書ける場合は特に問題がありません。
<template>
<div>
<div v-for="key1 in level1" :id="key1">
<span>{{ key1 }}</span>
<div v-for="key2 in level2" :id="key2">
<input v-model="form[key1][key2]">
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
form: {
tokyo: {
prop1: 0,
prop2: 0,
},
osaka: {
prop1: 0,
prop2: 0,
},
},
level1: ["tokyo", "osaka"],
level2: ["prop1", "prop2"],
};
},
};
</script>
うまく行かないケース
では上記のformの内容を1段上げてみるとどうでしょう。
<template>
<div>
<div v-for="key1 in level1" :id="key1">
<span>{{ key1 }}</span>
<div v-for="key2 in level2" :id="key2">
<!-- this[key1][key2]に行ってほしい -->
<input v-model="[key1][key2]">
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
tokyo: {
prop1: 0,
prop2: 0,
},
osaka: {
prop1: 0,
prop2: 0,
},
level1: ["tokyo", "osaka"],
level2: ["prop1", "prop2"],
};
},
};
</script>
エラーは出ませんが、値も変わりません。
内部的にどういう解釈になっているのか追っかけていないのでわかりませんが、とりあえず動作しません。
まとめ
上記のように、dataのトップレベルのプロパティ名を動的に指定する方法が見つかりませんでした。
通常はとりあえず1段下げれば回避できるのですが、
例えばvuexのストアの中にある値をv-modelで使いたい場合get/set形式のcomputed propertyにするのがよくありますが、computedは階層化できないので、1段下げることができません。
実は回避方法はひとつ見つけていて、このように遠回りにthisを置き換えると動きます。
<input v-model="$vnode.componentInstance[key1][key2]">
ただちょっと変化球ですしずっと使えるかどうかもわからないので、ストレートなやり方があったら教えて下さいませ。