目次

Vue.js 3.x で作る LabeledForm

要求

  • ラベル、入力コントロールを再利用可能な形でレイアウトしたい.
  • モバイル向けでないレイアウトの場合、ラベルと入力コントロールのラッパーの高さを同じにしたい.
  • 使用する CSS フレームワークに合わせて指定クラスやスタイルを調整可能にしたい.
    • カスタム CSS クラス、カスタムスタイルを props 経由で設定可能にする.
  • 入力内容にエラーが存在する場合、自動的にエラー用のスタイルを反映したい.

前提・制約

課題

仕様

コード

LabeledForm.js
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: `
    <div class="row" :class="mergedFormWrapperClasses" :style="formWrapperStyles">
      <div :class="computedLabelWrapperClasses" :style="labelWrapperStyles">
        <slot name="label"><label>{{ labelText }}</label></slot>
      </div>
      <slot></slot>
    </div>
  `,
  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:

labelText:

labelWrapperClasses:

labelWrapperStyles:

errors:

formErrorClass:

labelErrorClass:

Demo

シンプルなレイアウト