====== 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 ===== ==== シンプルなレイアウト ====