vuejs:vue3:labeled_form

Vue.js 3.x で作る LabeledForm

  • ラベル、入力コントロールを再利用可能な形でレイアウトしたい.
  • モバイル向けでないレイアウトの場合、ラベルと入力コントロールのラッパーの高さを同じにしたい.
  • 使用する CSS フレームワークに合わせて指定クラスやスタイルを調整可能にしたい.
    • カスタム CSS クラス、カスタムスタイルを props 経由で設定可能にする.
  • 入力内容にエラーが存在する場合、自動的にエラー用のスタイルを反映したい.
  • 主に Bootstrap3, Bootstrap4, Bootstrap5 を対象として想定している.
  • 検証結果のフィードバックは複雑になるため、実装しない.
  • ラベル部分もアイコンやタグなどを自由にデザインできるよう、スロットにするか?
  • ラベル、コントロール、エラーメッセージを保持するラッパーに対して、外部からクラス、スタイルを指定できること.
  • 入力内容にエラーが発生している場合は、エラーメッセージを設定することにより、エラーを視認性が高い状態で表示できること.
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 ;
  • type: Array
  • default: []
  • type: String
  • type: Array
  • default: []
  • type: Object
  • default: { paddingTop: '7px' }
  • type: Array
  • default: []
  • type: String
  • default: 'has-error' }
  • type: String
  • default: 'text-danger'

<html>

<labeled-form
  label-text="Test Label from props"
  :form-wrapper-classes="['mb-5']"
  :label-wrapper-classes="['col-sm-4', 'sm-text-right']"
  :label-wrapper-styles="{ paddingTop: '7px' }"
  :errors="errorMessages"
  form-error-class=""
  label-error-class="text-danger"
  control-error-class="has-error"
>
  <template #label>
    <span class="label label-info">Test</span> <label>Test Label</label>
  </template>
  <input-form type="text"
    :control-wrapper-classes="['col-sm-8']"
    :errors="errorMessages"
  >
  </input-form>
</labeled-form>

<script type=“module”>
import { createApp } from 'https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.2/vue.esm-browser.js';
import LabeledForm from '/_export/code/vuejs/vue3/labeled_form?codeblock=0';
import InputForm from '/_export/code/vuejs/vue3/input_form?codeblock=0';

const App = {

components: {
  InputForm: InputForm,
  labeledForm: LabeledForm
},
data() {
  return {
    errorMessages: ['error message A', 'error message B']
  }
}

}

createApp(App).mount('#app')
</script>

<link rel=“stylesheet” href=“/_export/code/vuejs/vue3/form_styles?codeblock=0”>

</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>

  • vuejs/vue3/labeled_form.txt
  • 最終更新: 2021/02/09 15:23
  • by admin