diff --git a/README.md b/README.md index b695483..a69466d 100644 --- a/README.md +++ b/README.md @@ -171,11 +171,12 @@ The accept values works makes use of the native HTML `accept` attribute. Read mo Please read the section on **custom upload templates** and how to integrate configs like *accept* to your custom template. -## Multiple images +### Multiple uploads -Multiple images — __not fully supported yet__ +#### Manual mode -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) +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/simple-schema-js#schema-keys). +In this mode each file has to be added manually and there is only one file seletable at a time. ```js Schemas.Posts = new SimpleSchema({ @@ -199,6 +200,33 @@ Schemas.Posts = new SimpleSchema({ }); ``` +#### Auto mode + +Use the `multiple: true` option, if you want to select multiple files at once and let them be added to the form automatically: + +```javascript +Schemas.Posts = new SimpleSchema({ + title: { + type: String, + max: 60 + }, + pictures: { + type: Array, + label: 'Choose file' // <- Optional + }, + "pictures.$": { + type: String, + autoform: { + afFieldInput: { + type: 'fileUpload', + collection: 'Images', + multiple: true + } + } + } +}); +``` + ## Custom file preview Your custom file preview template data context will be: diff --git a/lib/client/fileUpload.html b/lib/client/fileUpload.html index ba0a2c5..94fb464 100644 --- a/lib/client/fileUpload.html +++ b/lib/client/fileUpload.html @@ -24,7 +24,8 @@   {{progress.get}}% {{else}} - + {{/with}} {{/if}} {{/with}} diff --git a/lib/client/fileUpload.js b/lib/client/fileUpload.js index 0833c79..ffb25f9 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 multiQueue = new ReactiveVar([]); + Template.afFileUpload.onCreated(function () { const self = this; if (!this.data) { @@ -71,6 +74,18 @@ Template.afFileUpload.onCreated(function () { this.inputName = this.data.name; this.fileId = new ReactiveVar(this.data.value || false); this.formId = AutoForm.getFormId(); + this.multiple = this.data.atts.multiple; + + if (this.multiple) { + this.autorun(() => { + const queued = multiQueue.get(); + if (!this.fileId.get() && !this.currentUpload.get() && queued.length > 0) { + const file = queued.shift(); + uploadFile(file, self); + } + }) + } + return; }); @@ -112,6 +127,9 @@ Template.afFileUpload.helpers({ accept() { return Template.instance().accept; }, + multiple() { + return Template.instance().multiple; + }, inputAtts(formContext) { const { atts } = formContext; if (!atts) return; @@ -140,44 +158,64 @@ 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 && template.inputName.split('.')[0]; + const queued = multiQueue.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(); + multiQueue.set(queued); + return; + } + + 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.$(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(); +} \ No newline at end of file