Skip to content
Closed
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
35 changes: 33 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,12 @@ 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).

### 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)
### Multiple uploads

#### 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/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.

```javascript
Schemas.Posts = new SimpleSchema({
Expand All @@ -152,6 +156,33 @@ Schemas.Posts = new SimpleSchema({
})
```

#### Auto mode

Use `multiple: "multiple",` 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: "multiple"
}
}
}
})
```

### Custom file preview

Your custom file preview template data context will be:
Expand Down
2 changes: 2 additions & 0 deletions lib/client/autoform.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ AutoForm.addInputType('fileUpload', {
}
});

// single file

AutoForm._globalHooks.onSuccess.push(function (type) {
if (type === 'insert') {
try {
Expand Down
2 changes: 1 addition & 1 deletion lib/client/fileUpload.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
&nbsp;
<span class="progress">{{progress.get}}%</span>
{{else}}
<input data-files-collection-upload class="form-control af-file-upload-capture" type="file" />
<input data-files-collection-upload class="form-control af-file-upload-capture" multiple="{{multiple}}" type="file" />
{{/with}}
{{/if}}
{{/with}}
Expand Down
111 changes: 75 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 queue = new ReactiveVar([]);

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

Expand All @@ -93,6 +108,9 @@ Template.afFileUpload.helpers({
return null;
}
return template.collection.findOne({_id});
},
multiple() {
return Template.instance().multiple
}
});

Expand All @@ -116,44 +134,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();
}