目次

Vue.js 3.x Textarea Form コンポーネント

要求

コード

TextareaForm.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 TextareaForm = {
  template: `
    <div :class="computedControlWrapperClasses" :style="controlWrapperStyles">
      <textarea class="form-control"
        :class="controlClasses"
        :style="controlStyles"
        :value="value"
        v-bind="$attrs"
        @input="updateValue($event.target.value)"
      >
      </textarea>
      <div :class="computedMessageWrapperClasses" :style="messageWrapperStyles">
        <template v-for="msg in errors">
          <span>{{ msg }}</span><br>
        </template>
      </div>
    </div>
  `,
  props: {
    value:                 { type: String },
    errors:                { type: Array,  default: [] },
    controlWrapperClasses: { type: Array,  default: [] },
    controlWrapperStyles:  { type: Object, default: {} },
    controlClasses:        { type: Array,  default: [] },
    controlStyles:         { 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
      )
    })
    function updateValue(v) {
      context.emit('update:value', v)
    }
    return {
      computedControlWrapperClasses,
      computedMessageWrapperClasses,
      updateValue
    }
  }
};
export default TextareaForm;

Props

<html><style>th, td { padding: 12px !important }</style></html>

Property Type Default Description
value String v-model プロパティとして value を持つ
controlWrapperClasses Array [] textarea を囲う div タグに反映するクラス
controlWrapperStyles Object {} textarea を囲う div タグに反映するスタイル
controlClasses Array [] 入力コントロールに反映するクラス
controlStyles 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>

<textarea-form
  placeholder="placeholder text"
  :control-wrapper-classes="['col-sm-8', 'mb-5']"
  :errors="errors"
  v-model:value="boundText"
>
</textarea-form>
<textarea-form
  placeholder="placeholder text"
  :control-wrapper-classes="['col-sm-8']"
  v-model:value="boundText"
>
</textarea-form>
<button @click="clearError">ClearError</button>
<button @click="appendError">AppendError</button>

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

const App = {

components: {
  TextareaForm: TextareaForm
},
data() {
  return {
    boundText: null,
    errors: []
  }
},
methods: {
  clearError() {
    this.errors.splice(0, 1);
  },
  appendError() {
    this.errors.splice(0, 0, 'error message B')
  }
}

}

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