Giter VIP home page Giter VIP logo

vue-clip's Introduction

Introduction

Vue clip is a minimalistic and hackable file uploader for VueJs. I wrote this plugin due to the absence of well written file uploaders with fine-grained controls.

Version Build Status Downloads License

Features

  1. Written in vanilla Javascript.
  2. Weighs 17.9KB ( Minified and Gzip ), 57KB ( Minified ).
  3. Hackable to the core with custom events.
  4. Does not pollute DOM by adding unnecessary markup. Infact the component will create a single div element.

Quick Intro

<iframe src="https://www.youtube.com/embed/84_SwbPWjKo" type="text/html" width="640" height="360" frameborder="0"></iframe>

Setup

You can make use of module by installing it from npm or directly using it from CDN.

Npm

npm i --save vue-clip
import Vue from 'vue'
import VueClip from 'vue-clip'

Vue.use(VueClip)

Globally

Also, you can reference the script file via CDN which will add a global component called vue-clip to the Vue instance.

Basic Usage

<template>
  <vue-clip :options="options">
    <template slot="clip-uploader-action">
      <div>
        <div class="dz-message"><h2> Click or Drag and Drop files here upload </h2></div>
      </div>
    </template>

    <template slot="clip-uploader-body" scope="props">
      <div v-for="file in props.files">
        <img v-bind:src="file.dataUrl" />
        {{ file.name }} {{ file.status }}
      </div>
    </template>

  </vue-clip>
</template>

<script>
  export default {

    data () {
      return {
        options: {
          url: '/upload',
          paramName: 'file'
        }
      }
    }

  }
</script>

Configuration Options

Option Possible Values Description
url String, Function Url to be used for uploading files. This can be a string or a function ( in case your URL is dynamic )
method String, Function Http method to be used. Defaults to post.
parallelUploads Number Number of files to be uploaded in parallel.
maxFilesize Number, Object The file size in MB to be allowed. Also, you can pass an object with limit and error message.
paramName String Param name to be used for uploading file(s). Defaults to file.
uploadMultiple Boolean Whether or not to upload multiple files.
headers Object Http headers to be sent along each request.
maxFiles Number, Object a maximum number of files to be uploaded. You can also pass an object with limit and error message.
acceptedFiles Array, Object File types to be accepted. ['image/*', 'application/pdf'].
accept Function A custom function to be used for validating each file upload. This method receives a done callback. In the case of any errors, you must call done with a single error argument.

maxFilesize

The maxFilesize option defines the size of the file to be checked for when uploading files.

{
  maxFilesize: 1 // 1mb
}

// or

{
  maxFilesize: {
    limit: 1,
    message: '{{ filesize }} is greater than the {{ maxFilesize }}'
  }
}

maxFiles

The maxFiles option defines the maximum number of files to be uploaded.

{
  maxFiles: 5
}

// or

{
  maxFiles: {
    limit: 5,
    message: 'You can only upload a max of 5 files'
  }
}

acceptedFiles

The acceptedFiles option defines the mime types of files to be accepted.

// as an array of mime types

{
  acceptedFiles: ['image/*', 'application/pdf']
}

// as an object with an array of mime types
// and a custom error message

{
  acceptedFiles: {
    extensions: ['image/*'],
    message: 'You are uploading an invalid file'
  }
}

// as a plain, comma-delimited string

{
  acceptedFiles: 'image/*,application/pdf'
}

accept

The accept is a low-level method to run manual validations and return a formatted error string ( in the case of error).

{
  accept: function (file, done) {
    if (file.size > (1024 * 1024)) {
      done('File must be smaller than 1MB')
      return
    }

    done()
  }
}

Dragging

The most common requirement is to know when a user starts and stops dragging a file so that you can add some visual feedback to the UI. The easiest way is to make use of Scoped slots.

<template>
  <vue-clip :options="options">

    <template slot="clip-uploader-action" scope="params">
      <div v-bind:class="{'is-dragging': params.dragging}" class="upload-action">
        <h2> Click or Drag and Drop files here upload </h2>
      </div>
    </template>

  </vue-clip>
</template>

<style>
  .upload-action.is-dragging {
    background: green;
  }
</style>

Events

You can make use of vue-clip without writing any javascript code, but if you want low-level control over the upload behavior, consider listening to special events.

onInit(uploader)

Called every time the vue-clip is initiated and binds to DOM.

<template>
  <vue-clip :on-init="init">
  </vue-clip>
</template>

<script>
  export default {

    methods: {
      init (uploader) {
        // javascript uploader instance
      }
    }

  }
</script>

onAddedFile(file)

This event is invoked every time a new file gets uploaded. You can listen for this event, you want to have access to each file object within your own parent component.

<template>
  <vue-clip :on-added-file="addedFile">
  </vue-clip>
</template>

<script>
  export default {

    data: function () {
      return {
        files: []
      }
    }

    methods: {
      addedFile (file) {
        this.files.push(file)
      }
    }

  }
</script>

onRemovedFile(file)

This event is invoked every time the file has been removed. This is the nice place to make a request to your server for deleting the file.

<template>
  <vue-clip :on-removed-file="removedFile">
  </vue-clip>
</template>

<script>
  export default {

    methods: {
      removedFile (file) {
        this
        .$http
        .post(`delete/${file.customAttributes.id}`)
        .then(console.log)
        .catch(console.error)
      }
    }

  }
</script>

onSending(file, XHR, formData)

This event is emitted before making the upload HTTP request. So this is the time to modify the HTTP request and send some custom attributes.

<template>
  <vue-clip :on-sending="sending">
  </vue-clip>
</template>

<script>
  export default {

    methods: {
      sending (file, xhr, formData) {
        formData.append('_csrf', '<token>')
      }
    }

  }
</script>

onComplete(file, status, xhr)

This event is called when a file has been processed. It includes error, success both. 3rd argument will be the xhr response, if the error is returned from the server when uploading the file.

<template>
  <vue-clip :on-complete="complete">
  </vue-clip>
</template>

<script>
  export default {

    methods: {
      complete (file, status, xhr) {
        // Adding server id to be used for deleting
        // the file.
        file.addAttribute('id', xhr.response.id)
      }
    }

  }
</script>

onDragEnter

This event is invoked as soon as the user starts dragging the file.

<template>
  <vue-clip :on-drag-enter="dragging">
  </vue-clip>
</template>

<script>
  export default {

    methods: {
      dragging () {
        // user started dragging the file.
      }
    }

  }
</script>

onDragLeave

This event is invoked when the user stops dragging the file.

<template>
  <vue-clip :on-drag-leave="stoppedDragging">
  </vue-clip>
</template>

<script>
  export default {

    methods: {
      stoppedDragging () {
        // user stopped dragging the file.
      }
    }

  }
</script>

onDrop

This event is invoked when the user drops a file on the vue-clip area.

<template>
  <vue-clip :on-drop="drop">
  </vue-clip>
</template>

<script>
  export default {

    methods: {
      drop () {
        // user stopped dragging the file.
      }
    }

  }
</script>

onTotalProgress(progress, totalBytes, bytesSent)

This event returns the total upload progress for all the files. Think of it as the global progress indicator for multiple files uploaded together.

<template>
  <vue-clip :on-total-progress="totalProgress">
  </vue-clip>
</template>

<script>
  export default {

    methods: {
      totalProgress (progress, totalBytes, bytesSent) {
      }
    }

  }
</script>

onQueueComplete

The event is called when all files in the queue have been uploaded to the server.

<template>
  <vue-clip :on-queue-complete="queueCompleted">
  </vue-clip>
</template>

<script>
  export default {

    methods: {
      queueCompleted () {
      }
    }

  }
</script>

onMaxFiles

The event is called when maxFiles upload limit has been reached. This event will be fired n timesfor each file exceeding the limit. For example

  • maxFiles - 3
  • filesUploaded - 5
  • eventCalled - 2 times with file instance
<template>
  <vue-clip :on-max-files="maxFilesReached">
  </vue-clip>
</template>

<script>
  export default {

    methods: {
      maxFilesReached (file) {
      }
    }

  }
</script>

File Attributes

The file instance sent along events has following attributes.

Attribute Type Description
name String The client name of the file
status String String The file status, which can be success, error, queued, added.
width Number The file width. Only for images.
height Number The file height. Only for images.
bytesSent Number The total bytes sent to the server so far.
progress Number Total upload progress.
total Number The total number of bytes to be sent to the server.
type String The file mime-type.
size Number The file size on user disk.
dataUrl String File base64 data URL to be used for displaying images preview.
xhrResponse Object Server xhrResponse. Only contains response, responseText and statusCode
errorMessage String Error message when processing a file. If the error is returned from the server, it will be the value of XHR error. Also can be client errors for maxSize etc.
customAttributes Object Each file needs some custom attributes, for example server id to be used for deleting the files.

Adding/Accessing Custom Attributes

file.addAttribute('id', xhr.response.id)

// access id
file.customAttributes.id

Browser Support

  • Chrome 7+
  • Firefox 4+
  • IE 10+
  • Opera 12+
  • Safari 6+

Things to consider

Make sure you add class dz-message to the uploader action wrapped inside clip-uploader-action slot. This makes your entire action body clickable. There are ways to get around it, but I wanted to keep the API transparent, instead of adding a bunch of DOM elements behind the scenes.

<template slot="clip-uploader-action">
  <div>
    <div class="dz-message"><h2> Click or Drag and Drop files here upload </h2></div>
  </div>
</template>

vue-clip's People

Contributors

alexsasharegan avatar thetutlage avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-clip's Issues

Can't upload more after max hit

When setting maxFiles as part of options, if you upload the max number of files and then delete one, you cannot add more.

To reproduce:

  1. Set maxFiles: 3 in options
  2. Add a bind to delete uploads, e.g.
    removeFile(file) {
      this.vendor.logo = null;
      var index = this.$refs.vc.files.indexOf(file);
      this.$refs.vc.files.splice(index, 1);
    },

          <template slot="clip-uploader-body" scope="props">
            <div v-for="file in props.files">
              <img v-bind:src="file.dataUrl" v-on:click="removeFile(file)">
              {{ file.name }} {{ file.status }}
            </div>
          </template>
  1. Upload 3 images
  2. Click on one of the images to fire removeFile
  3. Try to upload another image and watch nothing happen, without any errors

Upload files with Laravel

Hi!

I'm trying to make it work with laravel but for now, nothing seems to work. I can't get the file data on the Laravel side. The example shown in the video use another routing system.

Is this component compatible with Laravel? How can I achieve to pass the datas to my Laravel controller?

Thanks in advance!

Setting the upload URL after component initialization

Hi,

I am currently using a <vue-clip> instance within a bootstrap modal, meaning the component is rendered alongside the modal when the page is loaded and only hidden/shown as needed.

The Problem

The upload URL is not yet known at that point in time and I would like to update it once a user has performed some action that will let us know which URL to use (e.g. /groups/{id}/upload).

I haven't figured out a way how to do this yet, vue-clip seems to ignore changes to its options.url value after initialization and I also can't update the XMLHTTPRequest.responseURL inside the onSending() method because that is read-only.

Any ideas how I could achieve that? If there is no way, please consider this a humble feature request ;)

Thanks for creating the library and cheers

Support Upload image from Clipboard

Hi,
It's can support directly upload image from Clipboard?
Sometimes we just want to quickly upload image from screen snap.
If it's support Ctrl + V to upload Clipboard image, it's so cool.

[Question] Events API

First of all thanks for a great component. I've just spent a few time trying to figure out a problem with my code handling vue-clip events. It turns out I was trying to use the v-on to listen for events but it was expected to pass a prop (with v-bind or the : syntax) with a function instead.

I'm quite new to vue but it seems the v-on syntax is the vue way of communicating with events. Using it also helps on debugging since the events and their data can be seen in the chrome console (with the vue extension).

Is there any particular reason the events API has been designed using props?

Bundle size

I think there is a bug in the bundling process:

I use package-size to check the sizes of vue and vue-clip:

package   size    minified  minified + gzipped
vue       162 kB  51.4 kB   18.4 kB
vue-clip  164 kB  59.1 kB   17.8 kB

When I checked the source code of your project (src folder), it can't be possible that it's as big a Vue.js, maybe Webpack is putting vue inside the bundle?

NPM links

NPM website doesn't link to this repo, you should probably insert some info in package.json

Also shouldn't this repo be moved to AdonisJS's github ?

I am just saying because it wasn't ease to reach the source code on github, I had to google it, which is unusual for NPM packages

Thanks for the great work btw :)

Pre-compile templates ?

Hello, I'm using Vue-Clip within my Nuxt project (https://github.com/nuxt) and get this error on render:

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

It works if I reference the compiler-included build in the web pack configuration of Nuxt like this:

build: { extend(config) { config.resolve.alias['vue'] = 'vue/dist/vue.common' } }

Is there another work-around ? Like pre-compiling templates of Vue-Clip ?

Thank you very much! (great plugin)

uploadMultiple doesnt seem to work

Hello!
Great plugin, thanks!
One problem so far - setting uploadMultiple: false doesnt seem to have any effect - Im still able to select multiple files in the file selector dialog. However, setting maxFiles: 1 does the trick but I have to clear files on upload to allow for re-upload. Is this just me or this behavior is counter-intuitive ?

Thanks!

method always is OPTIONS

I run small local router with POST trigger, but after select any file I get arror:
image
logs

{"time":"2017-08-04T12:31:44.60323609+05:00","id":"","remote_ip":"127.0.0.1","host":"127.0.0.1:1323","method":"OPTIONS","uri":"/","status":405, "latency":43517,"latency_human":"43.517µs","bytes_in":0,"bytes_out":37}

My code in .vue file (after import and use module in main.js):

export default {
  name: 'app',
  data() {
    return {
      tips: true,
      locale: 'en',
      options: {
        url: apiUrl,
        method: 'post',
        paramName: 'file',
        maxFileSize: {
          limit: 99,
          message: '{{ filesize }} is greater than the {{ maxFilesize }}'
        }
      }
    }
  }
}

How to configure global options?

Hello, I have a doubt, in my project it is necessary to configure the option headers in a global way in order not to have to instantiate it every time I use the vue-clip component.

I Would like to know if there is any way to do this?

Thank you and forgive my bad English, I'm Spanish speaking...

Uploader with existing images

Sometimes you'd want to use the uploader when editing something, not creating a new item, so the uploader shall have a list of existing images. The question is how to specify this in the files array? I'd think just adding objects with a url property, but if I do so now it fails with an error as it's not prepared for this.

Basic Usage Example has typo in it

In the "clip-uploader-body" in the basic example I think it should be
<div v-for="file in props.files"> instead of <div v-for="file in file.props">

Method to reset inner reference of files

Hello,

I suggest a new method which could be called to reset the array of fields from vue-clip data.
But this should not trigger onRemovedFile event, because you just want to remove files which template render.

Something like:

resetFiles() {
    this.files = [];
}

So you can call

this.$refs.uploader.resetFiles()

It's small, but very useful sometimes.

[Question] Best way to import with es2015 modules

A lot of libs these days are shipping a lib.esm.js file in their dist folder to enable the client to run the lib through their own bundler and get all the possible static analysis gains. Since there is no vue-clip.esm.js and this looks to be written with harmony modules, would you say the best alternative is to import like so: import VueClip from 'vue-clip/index'?

Progress for each file

Hi,

is there a way to get progress for each file separately, for example to show progress against each file?

thanks.

Double click

Hi, is there any simple way to prevent double a click from opening the file browser dialog twice?

File name manipulation and associating it with input data

How do we manipulate the file name , so that we can save it as a unique file and associate it with user data. If this is possible then I can change the file name according to user input parameter or id , and link user inputs to the file.

AutoStart option

It would be good to have an option to prevent automatic upload.

Vue - Clip window is undefined

I am trying to use vue-clip with vuetify and i get the following error

I added an undefined check in line 3543 for 'window' , it worked fine. So please check

error during render : /
ReferenceError: window is not defined
    at Object. (/Users/krishnamurthys/HCM/project-hcm/node_modules/vue-clip/dist/vue-clip.js:3543:15)
    at Object. (/Users/krishnamurthys/HCM/project-hcm/node_modules/vue-clip/dist/vue-clip.js:3547:5)
    at Object.LARGE_ARRAY_SIZE (/Users/krishnamurthys/HCM/project-hcm/node_modules/vue-clip/dist/vue-clip.js:3549:31)
    at webpack_require (/Users/krishnamurthys/HCM/project-hcm/node_modules/vue-clip/dist/vue-clip.js:30:30)
    at Object.defineProperty.value (/Users/krishnamurthys/HCM/project-hcm/node_modules/vue-clip/dist/vue-clip.js:508:18)
    at webpack_require (/Users/krishnamurthys/HCM/project-hcm/node_modules/vue-clip/dist/vue-clip.js:30:30)
    at Object. (/Users/krishnamurthys/HCM/project-hcm/node_modules/vue-clip/dist/vue-clip.js:649:18)
    at webpack_require (/Users/krishnamurthys/HCM/project-hcm/node_modules/vue-clip/dist/vue-clip.js:30:30)
    at Object. (/Users/krishnamurthys/HCM/project-hcm/node_modules/vue-clip/dist/vue-clip.js:63:15)
    at webpack_require (/Users/krishnamurthys/HCM/project-hcm/node_modules/vue-clip/dist/vue-clip.js:30:30)

REQUEST: Retry Support

Just started using this component, and so far love the amount of flexibility to customize it. Would it be possible to provide support for retries so if an error happens on file upload the component could retry? There can also be a :maxRetries=? an option that defines how many times the retry has to be made.

Flush Items after Upload

Given i am using this in a bootstrap modal.

How can i flush the items in the file.props array? so after opening the modal again the items are not present anymore..

far the best upload plugin for vuejs! really awesome
thanks max

Store files as data in parent through props

Would it be possible to move the files array into the parent, so it could use it for other purposes too? Just as the example under "basic usage" gets the options from the parent as a component prop.

Use case: we need to enable drag and drop reordering of already uploaded images, and then save this order along with the images. So vue-clip would store files in an array on the root data, and then we'd create an ordered array (computed), and base the display on that.

Loading files already existing on server

How can i load files already existing on server? Lets say i refreshed page and dont want to loose already uploadef files.
I have backend endpoint that returns array of urls of files existing on server, so now i just have inserti it into vue.

acceptedFiles.split is not a function

When using the syntax below I'm getting an error in the console saying that acceptedFiles.split is not a function. Switching to the object syntax, there is no error.

{
  acceptedFiles: ['image/*', 'application/pdf']
}

Resize image on the client before uploading

Hi,

I know this is not an easy request / question, but here it is:

Where can I have access to the file before the server being hit? I just want to resize the image to some specific percentage / size before uploading to speed-up the process.

I googled a bit and found that it is quite possible, so here is what I would suggest:

include an option to resize the filetype of image (something like this one ). I know this is not a clean-way, but you might find it interesting.

Thank you for any reply.

How to delete uploaded file?

I saw the method onRemovedFile(file) on README. the method will be invoked when the file was deleted.
but it seems there is no way to delete uploaded file. I have read source code.

what I need is the method DELETE(file) as following:

<template slot="clip-uploader-body" scope="props">
  <div v-for="(file, index) in props.files">
    <img v-bind:src="file.customAttributes.thumb_url" v-on:click="DELETE(file)"/>
    {{ file.name }} {{ file.status }}
  </div>
</template>

Clip#removeFile is the method I want. but I can't call the method inside clip-uploader-body slot, it's different scope.

refer this: https://vuejs.org/v2/guide/components.html#Compilation-Scope

test doesn't run on Win10

λ npm test

> [email protected] test C:\Users\tom-byrer\Documents\dev\github\vue\vue-clip
> karma start karma.conf.js

Ignore generating unminified version, since no UglifyJsPlugin provided
03 02 2017 03:29:13.684:INFO [karma]: Karma v1.4.1 server started at http://0.0.0.0:9876/
03 02 2017 03:29:13.688:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
03 02 2017 03:29:13.694:INFO [launcher]: Starting browser PhantomJS
03 02 2017 03:29:16.822:INFO [PhantomJS 2.1.1 (Windows 8 0.0.0)]: Connected on socket OCkqR6TtcYNrqLO2AAAA with id 14572959
PhantomJS 2.1.1 (Windows 8 0.0.0) INFO: 'You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html'

PhantomJS 2.1.1 (Windows 8 0.0.0) ERROR
  AssertionError: expected [ [Function], [Function] ] to deeply equal []
  at test/index.js:9114
PhantomJS 2.1.1 (Windows 8 0.0.0) ERROR
  AssertionError: expected [ [Function], [Function] ] to deeply equal []
  at test/index.js:9114
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 33 of 33 ERROR (0.148 secs / 0.083 secs)

TIA

maxFilesize message is not working

When specifying a message in the maxFilesize configuration, the template is not interpreted :

My configuration

          maxFilesize: {
            limit: 10,
            message: 'Ce fichier dépasse la taille maximum autorisée de {{ maxFilesize }} (Taille du fichier : {{ filesize }})'
          },

What I get on the screen :

Ce fichier dépasse la taille maximum autorisée de {{ maxFilesize }} (Taille du fichier : {{ filesize }})

Variables are not rendered with their actual values

Compatible with SSR

Actually, vue-clip is not compatible with server-side rendering, do you plan to make it compatible in the future?

How to stop an upload process

Is there a way to stop an upload process when it already started? I mean how to entirely kill the upload process.

base 64 resolution ?

Hi. is possible to config the resolution of the preview ? Currently is 120X120 on base64. Cheers

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.