From ca9b2d655971538ad3b94f25040982493f45841e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=BCster?= Date: Thu, 11 Apr 2019 13:09:26 +0200 Subject: [PATCH] added accept config using file type specifiers to filter upload selector by file extensions/types --- README.md | 25 ++++++++ lib/client/fileUpload.html | 2 +- lib/client/fileUpload.js | 115 +++++++++++++++++++++++++------------ 3 files changed, 105 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 10c68e9..ab10c0b 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,31 @@ Generate the form with `{{> quickform}}` or `{{#autoform}}` e.g.: Autoform should be wrapped in `{{#if Template.subscriptionsReady }}` which makes sure that template level subscription is ready. Without it the picture preview won't be shown. You can see update mode example [here](https://github.com/VeliovGroup/meteor-autoform-file/issues/9). +### Accept configuration + +You can configure the file selector, to only allow certain types of files using the `accept` property: + +```javascript +Schemas.Posts = new SimpleSchema({ + title: { + type: String, + max: 60 + }, + picture: { + type: String, + autoform: { + afFieldInput: { + type: 'fileUpload', + collection: 'Images', + accept: 'image/*' // or use explicit ext names like .png,.jpg + } + } + } +}); +``` + +The accept values works makes use of the native HTML `accept` attribute. Read more at the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers). + ### Multiple images // not fully supported yet If you want to use an array of images inside you have to define the autoform on on the [schema key](https://github.com/aldeed/meteor-simple-schema#schema-keys) diff --git a/lib/client/fileUpload.html b/lib/client/fileUpload.html index 4ce48f4..2f4a1d0 100644 --- a/lib/client/fileUpload.html +++ b/lib/client/fileUpload.html @@ -24,7 +24,7 @@   {{progress.get}}% {{else}} - + {{/with}} {{/if}} {{/with}} diff --git a/lib/client/fileUpload.js b/lib/client/fileUpload.js index 7948873..b7c57a1 100644 --- a/lib/client/fileUpload.js +++ b/lib/client/fileUpload.js @@ -4,6 +4,7 @@ import { AutoForm } from 'meteor/aldeed:autoform'; import { Template } from 'meteor/templating'; import { ReactiveVar } from 'meteor/reactive-var'; import { Mongo } from 'meteor/mongo'; +import { Random } from 'meteor/random' const defaultInsertOpts = { meta: {}, @@ -14,6 +15,8 @@ const defaultInsertOpts = { allowWebWorkers: true }; +const queue = new ReactiveVar([]); + Template.afFileUpload.onCreated(function () { const self = this; if (!this.data) { @@ -51,6 +54,7 @@ Template.afFileUpload.onCreated(function () { this.uploadTemplate = this.data.atts.uploadTemplate || null; this.previewTemplate = this.data.atts.previewTemplate || null; + this.accept = this.data.atts.accept || null; this.insertConfig = Object.assign({}, this.data.atts.insertConfig || {}); delete this.data.atts.insertConfig; this.insertConfig = Object.assign(this.insertConfig, _.pick(this.data.atts, Object.keys(defaultInsertOpts))); @@ -70,6 +74,18 @@ Template.afFileUpload.onCreated(function () { this.inputName = this.data.name; this.fileId = new ReactiveVar(this.data.value || false); this.formId = this.data.atts.id; + this.multiple = this.data.atts.multiple + + if (this.multiple) { + this.autorun(() => { + const queued = queue.get(); + if (!this.fileId.get() && !this.currentUpload.get() && queued.length > 0) { + const file = queued.shift(); + uploadFile(file, self); + } + }) + } + return; }); @@ -93,6 +109,12 @@ Template.afFileUpload.helpers({ return null; } return template.collection.findOne({_id}); + }, + multiple() { + return Template.instance().multiple + }, + accept() { + return Template.instance().accept; } }); @@ -116,44 +138,65 @@ Template.afFileUpload.events({ return false; }, 'change [data-files-collection-upload]'(e, template) { - if (e.currentTarget.files && e.currentTarget.files[0]) { - const opts = Object.assign({}, defaultInsertOpts, template.insertConfig, { - file: e.currentTarget.files[0] - }); - - const upload = template.collection.insert(opts, false); - let ctx; - try { - ctx = AutoForm.getValidationContext(template.formId); - } catch (exception) { - // Fix: "TypeError: Cannot read property '_resolvedSchema' of undefined" - ctx = AutoForm.getValidationContext(); + if (template.multiple && e.currentTarget.files && e.currentTarget.files.length > 1) { + + const formId = AutoForm.getFormId(); + const {minCount} = template; + const {maxCount} = template; + const schema = AutoForm.getFormSchema(formId); + const inputName = template.inputName.split('.')[0]; + const queued = queue.get(); + + for (let i = 0; i< e.currentTarget.files.length; i++) { + const file = e.currentTarget.files[i]; + queued.push(file); + AutoForm.arrayTracker.addOneToField(formId, inputName, schema, minCount, maxCount); } - upload.on('start', function () { - ctx.reset(); - template.currentUpload.set(this); - return; - }); - - upload.on('error', function (error) { - ctx.reset(); - ctx.addValidationErrors([{name: template.inputName, type: 'uploadError', value: error.reason}]); - template.$(e.currentTarget).val(''); - return; - }); - - upload.on('end', function (error, fileObj) { - if (!error) { - if (template) { - template.fileId.set(fileObj._id); - } - } - template.currentUpload.set(false); - return; - }); - - upload.start(); + queue.set(queued) + return void 0 + } + + if (e.currentTarget.files && e.currentTarget.files[0]) { + uploadFile(e.currentTarget.files[0], template) } } }); + +function uploadFile (file, template) { + const opts = Object.assign({}, defaultInsertOpts, template.insertConfig, {file}); + + const upload = template.collection.insert(opts, false); + let ctx; + try { + ctx = AutoForm.getValidationContext(template.formId); + } catch (exception) { + // Fix: "TypeError: Cannot read property '_resolvedSchema' of undefined" + ctx = AutoForm.getValidationContext(); + } + + upload.on('start', function () { + ctx.reset(); + template.currentUpload.set(this); + return; + }); + + upload.on('error', function (error) { + ctx.reset(); + ctx.addValidationErrors([{name: template.inputName, type: 'uploadError', value: error.reason}]); + template.$("[data-files-collection-upload]").val(''); + return; + }); + + upload.on('end', function (error, fileObj) { + if (!error) { + if (template) { + template.fileId.set(fileObj._id); + } + } + template.currentUpload.set(false); + return; + }); + + upload.start(); +}