====== Vue.js 3.x で作る LabeledForm ======
===== 要求 =====
* ラベル、入力コントロールを再利用可能な形でレイアウトしたい.
* モバイル向けでないレイアウトの場合、ラベルと入力コントロールのラッパーの高さを同じにしたい.
* 使用する CSS フレームワークに合わせて指定クラスやスタイルを調整可能にしたい.
* カスタム CSS クラス、カスタムスタイルを props 経由で設定可能にする.
* 入力内容にエラーが存在する場合、自動的にエラー用のスタイルを反映したい.
===== 前提・制約 =====
* 主に Bootstrap3, Bootstrap4, Bootstrap5 を対象として想定している.
* 検証結果のフィードバックは複雑になるため、実装しない.
===== 課題 =====
* ラベル部分もアイコンやタグなどを自由にデザインできるよう、スロットにするか?
===== 仕様 =====
* ラベル、コントロール、エラーメッセージを保持するラッパーに対して、外部からクラス、スタイルを指定できること.
* 入力内容にエラーが発生している場合は、エラーメッセージを設定することにより、エラーを視認性が高い状態で表示できること.
===== コード =====
import { computed } from 'https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.2/vue.esm-browser.js';
import { getWrapClass } from 'https://wws.jp/_export/code/vuejs/vue3/form_utils?codeblock=0';
const LabeledForm = {
template: `
`,
props: {
errors: { type: Array, default: [] },
formWrapperClasses: { type: Array, default: [] },
formWrapperStyles: { type: Object, default: {} },
labelWrapperClasses: { type: Array, default: [] },
labelWrapperStyles: { type: Object, default: { paddingTop: '7px' } },
labelText: { type: String },
formErrorClass: { type: String, default: 'has-error' },
labelErrorClass: { type: String, default: 'text-danger' },
},
components: {},
setup(props, context) {
const mergedFormWrapperClasses = computed(() => {
return getWrapClass(
props.errors,
props.formWrapperClasses,
props.formErrorClass
)
})
const computedLabelWrapperClasses = computed(() => {
return getWrapClass(
props.errors,
props.labelWrapperClasses,
props.labelErrorClass
)
})
return {
mergedFormWrapperClasses,
computedLabelWrapperClasses,
}
}
}
export default LabeledForm ;
===== Props =====
==== formWrapperClasses: ====
* type: Array
* default: []
==== labelText: ====
* type: String
==== labelWrapperClasses: ====
* type: Array
* default: []
==== labelWrapperStyles: ====
* type: Object
* default: { paddingTop: '7px' }
==== errors: ====
* type: Array
* default: []
==== formErrorClass: ====
* type: String
* default: 'has-error' }
==== labelErrorClass: ====
* type: String
* default: 'text-danger'
===== Demo =====
==== シンプルなレイアウト ====
Test