Vueを使用して簡単なフォームビルダーを作成します。ここで、ユーザーがメニューのボタンをクリックしてフォームにさまざまなフォームフィールドを追加します。追加するフォームフィールドが1種類だけの場合は、私はこのようなものでそれを行うことができました( https://jsfiddle.net/u6j1uc3u/32/ ):
<div id="app">
<form-input v-for="field in fields"></form-input>
<button type="button" v-on:click="addFormElement()">Add Form Element</button>
</div>
<script type="x-template" id="form-input">
<div>
<label>Text</label>
<input type="text" />
</div>
</script>
そして:
Vue.component('form-input', {
template: '#form-input'
});
new Vue({
el: '#app',
data: {
fields: [],
count: 0
},
methods: {
addFormElement: function() {
this.fields.Push({type: 'text', placeholder: 'Textbox ' + (++this.count)});
}
}
})
しかし、フォームフィールドのタイプ(入力、ファイル、選択など)が複数ある場合はどうでしょうか。タイプごとに異なるコンポーネントを作成することを考えていましたが、フォーム要素の単一のリストに複数のタイプのコンポーネントをどのように表示しますか?
fields
配列のデータに基づいて、さまざまなタイプの子コンポーネントを持つコンポーネントを作成できますか?
または、私が見逃しているこの状況に対処するためのより良い方法はありますか?私はVueの学習を始めたばかりなので、どんな助けにも感謝します!
OK、それで私は動的要素を調べて、これを一緒にまとめることができました:
Vue.component('form-input', {
template: '#form-input'
});
Vue.component('form-select', {
template: '#form-select'
});
Vue.component('form-textarea', {
template: '#form-textarea'
});
new Vue({
el: '#app',
data: {
fields: [],
count: 0
},
methods: {
addFormElement: function(type) {
this.fields.Push({
'type': type,
id: this.count++
});
}
}
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<div id="app">
<component v-for="field in fields" v-bind:is="field.type" :key="field.id"></component>
<button type="button" v-on:click="addFormElement('form-input')">Add Textbox</button>
<button type="button" v-on:click="addFormElement('form-select')">Add Select</button>
<button type="button" v-on:click="addFormElement('form-textarea')">Add Textarea</button>
</div>
<script type="x-template" id="form-input">
<div>
<label>Text</label>
<input type="text" />
</div>
</script>
<script type="x-template" id="form-select">
<div>
<label>Select</label>
<select>
<option>Option 1</option>
<option>Option 2</option>
</select>
</div>
</script>
<script type="x-template" id="form-textarea">
<div>
<label>Textarea</label>
<textarea></textarea>
</div>
</script>
したがって、fields
配列の各項目に新しいform-input
コンポーネントを作成する代わりに、フィールドのcomponent
プロパティを介して正しいコンポーネントに関連付けられている新しいtype
を作成しています
form-input
コンポーネントのプロパティとしてフィールドオブジェクトを渡し、type
を動的にすることができます。
Vue.component('form-input', {
template: '#form-input',
props: ['field']
})
new Vue({
el: '#app',
data: {
fields: [],
inputType: '',
count: 0
},
methods: {
addFormElement(val) {
this.fields.Push({type: val, placeholder: 'Textbox ' + (++this.count)});
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<h3>Add form element</h3>
<select size="3" v-model='inputType' @click="addFormElement(inputType)">
<option value="text">Text</option>
<option value="checkbox">Checkbox</option>
<option value="radio">Radio</option>
</select>
<p>
<form-input v-for="field in fields" :field="field"></form-input>
</p>
</div>
<template id="form-input">
<div>
<label>{{ field.type }}</label>
<input :type="field.type" />
</div>
</template>
回答のコードに基づいて、フォームコントロールのそれぞれに動的コンテンツを追加することもできます(完全な概念は、次の site で確認できます)。
Vue.component('form-input', {
template: '#form-input'
, props: ['label','cnt']
});
Vue.component('form-select', {
template: '#form-select'
, props: ['label','cnt']
});
Vue.component('form-textarea', {
template: '#form-textarea'
, props: ['label','cnt']
});
new Vue({
el: '#app',
data: {
fields: [],
count: 0
}
, mounted() {
// fetch those from back-end
this.addFormElement('form-input','lbl', "form-input-content")
this.addFormElement('form-textarea','lbl', "form-textarea-content")
var select_cnt = [
{'value': 1, 'text': 'item-01'},
{'value': 2, 'text': 'item-02'}
]
this.addFormElement('form-select','some-label',select_cnt)
}
, methods: {
addFormElement: function(type,label,cnt) {
this.fields.Push({
'type': type
, id: this.count++
, 'label':label
, 'cnt':cnt
});
}
}
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<div id="app">
<component v-for="field in fields" v-bind:is="field.type" :key="field.id" :cnt="field.cnt" :label="field.label"></component>
</div>
<script type="x-template" id="form-input">
<div v-on:keyup.tab="this.document.execCommand('selectAll',false,null);">
<label>{{label}}</label>
<input type="text" :value="cnt"/>
</div>
</script>
<script type="x-template" id="form-textarea">
<div v-on:keyup.tab="this.document.execCommand('selectAll',false,null);">
<label>{{label}}</label>
<textarea :value="cnt"></textarea>
</div>
</script>
<script type="x-template" id="form-select">
<div>
<label>Select</label>
<select>
<option v-for="oitem in cnt" :value="oitem.value">{{oitem.text}}</option>
</select>
</div>
<div v-html="cnt"></div>
</script>