vsivsi / meteor-file-collection

Extends Meteor Collections to handle file data using MongoDB gridFS.
http://atmospherejs.com/vsivsi/file-collection
Other
159 stars 37 forks source link

Template Data Context to use with metadata OR How to use it with Template...events() ? #160

Open juliomac opened 7 years ago

juliomac commented 7 years ago

My app is working fine for upload using the code from examples.

However, the examples are placing the code on Meteor.startup(). I need to get information from the template Data context in order to fill in the metadata fields. In Meteor.startup() I don't get the information.

For instance, iron-router renders me a template with CityId="nyc". I want to upload photo with metada CityId="nyc". It seems like I can only setup metadata once at startup or onRendered.

See the code I am trying to use:

    var dataContext = Blaze.getData(Blaze.currentView);
 var owner = Meteor.userId();
 var    CityId = dataContext._id;

     CityPhotosGridFS.resumable.on('fileAdded', function (file) {
    CityPhotosGridFS.insert({
        _id: file.uniqueIdentifier, 
        filename: file.fileName,
        contentType: file.file.type,
        metadata: {
            owner: owner,
            CityId: CityId
        }
        },
        function (err, _id) { 
            if (err) { return console.error("File creation failed!", err); }
            CityPhotosGridFS.resumable.upload();
        }
    );
});

This myfile.resumable.om('filAdded', ... confuses me I guess. Is there a way to use it with standard Template...events() ?

vsivsi commented 7 years ago

You can probably define the resumable.on(...) handlers in the template onRendered() callback. Just do it before you setup the resumable assignDrop (and/or assignBrowse) DOM target element.

vsivsi commented 7 years ago

So, for example here: https://github.com/vsivsi/meteor-file-sample-app/blob/master/sample.coffee#L26

juliomac commented 7 years ago

Hi @vsivsi ! Thanks for the prompt support!

I have done like you suggested. I have put both assignDrop and resumable.on inside onRendered().

The problem is that the metadata is not updated! It picks up the data of the first time it rendered only. For example, if I first render for CityId= "nyc" and later go to page with CityId="Boston", the metadata will not be updated. It will still show CityId= "nyc".

Meteor simply don't pass again though function onRendered() where we placed the resumable.on() function.

I also tried having resumable.on() inside a template...helper(), which is always re-run. But it gives errors and upload files with zero size.

juliomac commented 7 years ago

I laso tried using this.autorun(function()trick inside onRendered to force it to re-run as suggested HERE.

In fact it works nicely and re-runs part of the code. However, nothing inside resumable.onis re-run. Thus, metadata keeps immutable once define for the first time.

This is what I did:

Template.Cities.onRendered(function () {
 this.autorun(function() {
    Template.currentData();
    var dataContext = Blaze.getData(Blaze.currentView); // Could use either currentData or Blaze to get context
    var owner = Meteor.userId();
    var CityId = dataContext._id;

 CityPhotosGridFS.resumable.on('fileAdded', function (file) {
    console.log("passed here once");                     // console shows this only once despite autorun()
    CityPhotosGridFS.insert({
        _id: file.uniqueIdentifier, 
        filename: file.fileName,
        contentType: file.file.type,
        metadata: {
        owner: owner,
        CityId: CityId
        }
    },
    function (err, _id) { 
        if (err) { return console.error("File creation failed!", err); }
        CityPhotosGridFS.resumable.upload();
      }
        );
      });
  });
});
vsivsi commented 7 years ago

I didn't realize that the metadata could change after rendering... in that case you are gong to need to find a way to make your up-to-date metadata available to the resumable handler functions. I think you are on the right track with the code above.

Declaring a variable to hold a metadata object visible to the scope where the resumable handlers are declared. Then keep it updated using template autorun or helper functions. You don't want to redeclare the fileAdded handler in the autorun though. You should declare the shared variable in the onRendered, keep it updated in the autorun, and use it in the fileAdded handler.

Sorting out variable scoping like this is a JavaScript / Meteor client / resumable.js programming question that has nothing really to do with file-collection itself. (Resumable.js is an independent project).

I'm happy to help, but answering basic programming questions like this in a github issue without understanding the whole scope of your app and its requirements is going to be of limited usefulness.

juliomac commented 7 years ago

Thanks @vsivsi, taking the fileAdded handler out of the autorun() loop did the trick.

So far could only pass the shared variable to the resumable.on callback function as global as they are not visible outside autorun(). Not very elegant, but works. Passing as extra arguments to the resumable.on('fileAdded') callback does not work either.