vuematerial/vue-material

View on GitHub
src/components/MdField/MdFile/MdFile.vue

Summary

Maintainability
Test Coverage
F
12%
<template>
  <div class="md-file">
    <md-file-icon class="md-file-icon" :class="iconClass" @click.native="openPicker" />

    <input
      class="md-input"
      readonly
      v-model="model"
      v-bind="{ disabled, required, placeholder }"
      @click="openPicker"
      @blur="onBlur">

    <input type="file" ref="inputFile" v-bind="attributes" v-on="$listeners" @change="onChange" />
  </div>
</template>

<script>
  import MdUuid from 'core/utils/MdUuid'
  import MdFileIcon from 'core/icons/MdFileIcon'
  import MdFieldMixin from '../MdFieldMixin'

  export default {
    name: 'MdFile',
    components: {
      MdFileIcon
    },
    props: {
      id: {
        type: String,
        default: () => 'md-file-' + MdUuid()
      },
      name: String
    },
    computed: {
      iconClass () {
        return {
          'md-disabled': this.disabled
        }
      }
    },
    mixins: [MdFieldMixin],
    inject: ['MdField'],
    methods: {
      getMultipleName (files) {
        let names = [];

        [...files].forEach(({ name }) => names.push(name))

        return names.join(', ')
      },
      getFileName (files, target) {
        if (!files || files.length === 0) {
          return target.value.split('\\').pop()
        }

        if (files.length > 1) {
          return this.getMultipleName(files)
        }

        if (files.length === 1) {
          return files[0].name
        }

        return null
      },
      openPicker () {
        this.onFocus()
        this.$refs.inputFile.click()
      },
      onChange ($event) {
        this.onFileSelected($event)
      },
      onFileSelected ({ target, dataTransfer }) {
        const files = target.files || dataTransfer.files

        this.model = this.getFileName(files, target)
        this.$emit('md-change', files || target.value)
      }
    },
    created () {
      this.MdField.file = true
    },
    beforeDestroy () {
      this.MdField.file = false
    }
  }
</script>

<style lang="scss">
  .md-file {
    display: flex;
    flex: 1;

    input[type="file"] {
      width: 1px;
      height: 1px;
      margin: -1px;
      padding: 0;
      overflow: hidden;
      position: absolute;
      clip: rect(0 0 0 0);
      border: 0;
    }

    .md-file-icon {
      &:not(.md-disabled) {
        cursor: pointer;
      }

      &.md-disabled {
        pointer-events: none;
      }
    }
  }
</style>