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
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

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 @@
 
<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" type="file" accept="{{accept}}" />
{{/with}}
{{/if}}
{{/with}}
Expand Down
115 changes: 79 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 @@ -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)));
Expand All @@ -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;
});

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

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