Vue.js 3.x RadioForm コンポーネント
要求
Radio タグのエラーメッセージ表示付きコンポーネント
コード
- RadioForm.js
import { computed } from 'https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.2/vue.esm-browser.js'; import { getWrapClass, generalizeOptions } from 'https://wws.jp/_export/code/vuejs/vue3/form_utils?codeblock=0'; const RadioForm = { template: ` <div :class="computedControlWrapperClasses" :style="controlWrapperStyles"> <label v-for="(opt, idx) in computedOptions" :class="optionClasses" :style="optionStyles" > <input type="radio" :value="opt.value" :checked="opt.value === value" @change="$emit('update:value', $event.target.value)" > {{ opt.title }} </label> <div :class="computedMessageWrapperClasses" :style="messageWrapperStyles"> <template v-for="msg in errors"> <span>{{ msg }}</span><br> </template> </div> </div> `, props: { value: { type: String }, options: { type: Array, default: [] }, errors: { type: Array, default: [] }, controlWrapperClasses: { type: Array, default: [] }, controlWrapperStyles: { type: Object, default: {} }, controlClasses: { type: Array, default: [] }, controlStyles: { type: Object, default: {} }, optionClasses: { type: Array, default: ['radio-inline'] }, optionStyles: { type: Object, default: {} }, messageWrapperClasses: { type: Array, default: [] }, messageWrapperStyles: { type: Object, default: {} }, controlErrorClass: { type: String, default: 'has-error' }, messageErrorClass: { type: String, default: 'text-danger' }, }, setup(props, context) { const computedControlWrapperClasses = computed(() => { return getWrapClass( props.errors, props.controlWrapperClasses, props.controlErrorClass ) }) const computedMessageWrapperClasses = computed(() => { return getWrapClass( props.errors, props.messageWrapperClasses, props.messageErrorClass ) }) const computedOptions = computed(() => { return generalizeOptions(props.options) }) return { computedControlWrapperClasses, computedMessageWrapperClasses, computedOptions } } }; export default RadioForm;
Props
<html><style>th, td { padding: 12px !important }</style></html>
| Property | Type | Default | Description |
|---|---|---|---|
| options | Array | [] | select タグの選択肢 option を指定 { title: 表示名, value: 値 } 形式のオブジェクトを要素とする配列 または、要素に “title” プロパティが存在しない場合、単に値の配列として { title: 値, value: 値 } の配列に自動的に変換される |
| value | String | v-model プロパティとして value を持つ | |
| controlWrapperClasses | Array | [] | select を囲う div タグに反映するクラス |
| controlWrapperStyles | Object | {} | select を囲う div タグに反映するスタイル |
| controlClasses | Array | [] | 入力コントロールに反映するクラス |
| controlStyles | Object | {} | 入力コントロールに反映するスタイル |
| optionClasses | Array | [] | 選択肢に反映するクラス |
| optionStyles | Object | {} | 選択肢に反映するスタイル |
| messageWrapperClasses | Array | [] | エラーメッセージを囲う div タグに反映するクラス |
| errors | Array | [] | エラーメッセージの配列 |
| controlErrorClass | String | 'has-error' | コントロールに反映するエラークラス |
| messageErrorClass | String | 'text-danger' | エラーメッセージに反映するエラークラス |
Events
<html><style>th, td { padding: 12px !important }</style></html>
| Event | Value |
|---|---|
| update:value | 選択された値 |
Demo
<html>
<h3>コンポーネント実装</h3> <radio-form :options="options" :errors="errors" v-model:value="boundValue" :control-wrapper-classes="['radio', 'col-sm-12']" > </radio-form> <br> <h3>データバインディング確認用フォーム</h3> <radio-form :options="options" :errors="errors" v-model:value="boundValue" :control-wrapper-classes="['radio', 'col-sm-12']" :option-classes="['radio']" > </radio-form> <input type="text" v-model="boundValue"> <button @click="clearError">ClearError</button> <button @click="appendError">AppendError</button> <button @click="showValue">ShowValue</button>
<script type=“module”>
import { createApp } from 'https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.2/vue.esm-browser.js';
import RadioForm from '/_export/code/vuejs/vue3/radio_form?codeblock=0';
const App = {
components: {
radioForm: RadioForm
},
data() {
return {
boundValue: 'AAA',
// options: ['ABC', 'XYZ', 'AAA'],
options: [
{title: 'ABCタイトル', value: 'ABC'},
{title: 'XYZタイトル', value: 'XYZ'},
{title: 'AAAタイトル', value: 'AAA'}
],
errors: []
}
},
methods: {
clearError() {
this.errors.splice(0, 1);
},
appendError() {
this.errors.splice(0, 0, 'error message B')
},
showValue() {
console.log(this.boundValue)
}
}
}
createApp(App).mount('#app')
</script>
</html>
<html><style>
h2.page-header {
font-weight: 600; font-size: 2.4rem; position: relative; padding: 10px 0 10px 16px; margin-top: 3rem !important; margin-bottom: 2rem !important;
}
h2:before {
content: ""; position: absolute; top: 0; left: 0; width: 6px; height: 100%; background: #ccc;
}
div#disqus__thread {
width: 100% !important;
}
</style></html>