0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Vuelidate】親子間での利用

Last updated at Posted at 2021-07-12

子コンポーネントにrefで値を設定してやれば
this.\$refsから子コンポーネントの状態を取ってくることができます。
今回の場合はthis.\$refs["vali-files"].\$vからvuelidateの機能が利用できる。
利点は子に各vuelidateのルールを切り分けるので、フォームが増えても1ファイル1ルールで肥大化が避けられます。

親コンポーネント
<template>
  <form>
    <Files ref="vali-files" />
    <v-btn class="mr-4" @click="mySubmit">出力</v-btn>
    <v-btn @click="myClear">リセット</v-btn>
  </form>
</template>
<script>
import Files from "~/components/files.vue";
import { mapState, mapMutations, mapGetters, mapActions } from "vuex";
export default {
  components: { Files },
  data({}) {
    return {
      valis: {},
      comps: {},
    };
  },
  computed: {
    ...mapState("state-cms", ["$postData"]),
  },
  methods: {
    mySubmit() {
      let errorLen = 0;
      for (let key in this.valis) {
        this.valis[key].$touch();
        if (this.valis[key].$invalid) errorLen++;
      }
      //失敗… returnで中断
      if (errorLen) return;
      //成功!以下サーバー処理
      //this.exportFiles();
    },
    myClear() {
      for (let key in this.valis) {
        this.valis[key].$reset();
      }
      this.comps["vali-files"].files = [];
    },
  },
  created() {},
  mounted() {
    for (let key in this.$refs) {
      if (key.match(/^(vali-)/) !== null) {
        this.comps[key] = this.$refs[key];
        this.valis[key] = this.$refs[key].$v;
      }
    }
  },
};
</script>
子コンポーネント
<template>
  <v-container>
    <v-row
      class="text-center"
      @dragover.prevent
      @dragenter="onDragEnter"
      @dragleave="onDragLeave"
      @drop="onDrop"
    >
      <v-file-input
        v-model="files"
        color="deep-purple accent-4"
        counter
        label="参照するJSON:例… ~archive/000xxxx.json ※ドラッグ&ドロップ可"
        multiple
        required
        placeholder="あなたはファイルを選ぶ"
        prepend-icon="mdi-paperclip"
        outlined
        :show-size="1000"
        :background-color="isDragging ? 'blue' : 'null'"
        :error-messages="filesErrors($v.files)"
        @change="$v.files.$touch()"
        @blur="$v.files.$touch()"
      >
        <template v-slot:selection="{ index, text }">
          <v-chip
            v-if="index < 2"
            color="deep-purple accent-4"
            dark
            label
            small
            >{{ text }}</v-chip
          >
          <span
            v-else-if="index === 2"
            class="overline grey--text text--darken-3 mx-2"
            >+{{ files.length - 2 }} File(s)</span
          >
        </template>
      </v-file-input>
    </v-row>
  </v-container>
</template>
<script>
import { mapState, mapMutations, mapGetters, mapActions } from "vuex";
import { validationMixin } from "vuelidate";
import { required, maxLength, email } from "vuelidate/lib/validators";
export default {
  mixins: [validationMixin],
  validations: {
    files: {
      required,
      //jsonかどうか正しいかどうかを判別する
      async chkJson(val) {
        if (!val.length) return false;
        const jsonFlg = val[0].type.match(/json/);
        if (jsonFlg === null) {
          return false;
        } else {
          const reader = new FileReader();
          await this.files[0].text().then((data) => {
            this.$updatePostData({ key: "srcJson", val: data });
            this.$updatePostData({ key: "srcJsonName", val: val[0].name });
          });
          return true;
        }
      },
    },
  },
  props: [],
  data({}) {
    return {
      isDragging: false,
      dragCount: 0,
      files: [],
    };
  },
  computed: {},
  methods: {
    ...mapMutations("state-cms", ["$updatePostData"]),
    onDrop(e) {
      e.preventDefault();
      e.stopPropagation();
      this.isDragging = false;
      const _files = e.dataTransfer.files;
      for (const file in _files) {
        if (!isNaN(file)) {
          //filesはファイル以外のデータが入っており、ファイルの場合のみキー名が数字になるため
          this.files.push(_files[file]);
        }
      }
      this.files =
        this.files.length > 1
          ? this.files.splice(1, this.files.length - 1)
          : this.files;
    },
    onDragEnter(e) {
      e.preventDefault();
      this.isDragging = true;
      this.dragCount++;
    },
    onDragLeave(e) {
      e.preventDefault();
      this.dragCount--;
      if (this.dragCount <= 0) {
        this.isDragging = false;
      }
    },
    filesErrors(_files) {
      const errors = [];
      if (!_files.$dirty) return errors;
      if (!_files.required) {
        errors.push("Form is required.");
        return errors;
      }
      !_files.chkJson && errors.push("JSONじゃない!!");
      return errors;
    },
  },
};
</script>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?