Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion lib/client/fileUpload.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
&nbsp;
<span class="progress">{{progress.get}}%</span>
{{else}}
<input data-files-collection-upload class="form-control af-file-upload-capture" type="file" accept="{{accept}}" />
<input data-files-collection-upload class="form-control af-file-upload-capture" type="file" accept="{{accept}}"
multiple="{{#if multiple}}multiple{{/if}}" />
{{/with}}
{{/if}}
{{/with}}
Expand Down
110 changes: 74 additions & 36 deletions lib/client/fileUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {},
Expand All @@ -14,6 +15,8 @@ const defaultInsertOpts = {
allowWebWorkers: true
};

const multiQueue = new ReactiveVar([]);

Template.afFileUpload.onCreated(function () {
const self = this;
if (!this.data) {
Expand Down Expand Up @@ -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;
});

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}