2

I'm using CollectionFS to allow image uploads. The image uploads need to belong to specific posts. I followed the steps from the documentation - Storing FS.File references in your objects - however, I'm having a hard time displaying the image of the associated post.

The post currently saves with a postImage that references an image._id - this part is working fine. However, I am unsure how to display the actual photo, as it will need to grab the photo from the images collection (the post collection just saves an ID to reference).

post-list.html

<template name="postList">
<tr data-id="{{ _id }}" class="{{ postType }}">
    ...
    <td><textarea name="postContent" value="{{ postContent }}"></textarea> </td> 
    <td>{{ postImage._id }} </td> // This currently displays the correct image._id, but I would like to display the image,
    <td><button class="delete tiny alert">Delete</button></td>
</tr>
</template>

post-list.js

Template.postList.helpers({

  posts: function() {
    var currentCalendar = this._id;
    return Posts.find({calendarId: currentCalendar}, {sort: [["postDate","asc"]] });  
  }
});

post-form.js - This form creates a new Post and Image. The Image._id is saved to the Post.postImage.

Template.postForm.events({

  // handle the form submission
  'submit form': function(event) {

    // stop the form from submitting
    event.preventDefault();

    // get the data we need from the form
    var file = $('.myFileInput').get(0).files[0];
    var fileObj = Images.insert(file);
    var currentCalendar = this._id;
    var newPost = {
      ...
      calendarId: currentCalendar,
      owner: Meteor.userId(),
      postImage: fileObj,
    };    

    // create the new poll
    Posts.insert(newPost);
  }
});
JeremyE
  • 1,368
  • 4
  • 20
  • 40

2 Answers2

1

use reywood:publish-composite and dburles:collection-helpers so;

Collections || collections.js

Posts = new Mongo.Collection('posts');
Images = new FS.Collection("files", {
  stores: [
     // Store gridfs or fs
  ]
});

Posts.helpers({
  images: function() {
    return Images.find({ postId: this._id });
  }
});

Template || template.html

<template name="postList">
  {{# each posts }}
    {{ title }}
    {{# each images }} 
      <img src="{{ url }}">
    {{/each}}
  {{/each}}
</template>

Client || client.js

Template.postList.helpers({
  posts: function() {
    return Posts.find();
  }
});

Template.postList.events({
  // handle the form submission
  'submit form': function(event, template) {

  // stop the form from submitting
  event.preventDefault();

  // get the data we need from the form
  var file = template.find('.myFileInput').files[0];

  Posts.insert({
    calendarId: this._id,
    owner: Meteor.userId()
  }, function(err, _id) {
    var image = new FS.File(file);

    file.postId = _id;

    if (!err) {
      Images.insert(image);
    }
  });
  }
});

Router || router.js

Router.route('/', {
  name: 'Index',
  waitOn: function() {
    return Meteor.subscribe('posts');
  }
});

Server || publications.js

Meteor.publishComposite('posts', function() {
  return {
    find: function() {
      return Posts.find({ });
    },

    children: [
      {
        find: function(post) {
          return Images.find({ postId: post._id });
        }
      }
    ]
  }
});
yasaricli
  • 2,433
  • 21
  • 30
0

When using CollectionFS, on the client side you need to ensure that your subscriptions are correctly defined. This is the biggest stumbling block i've encountered with my developers in using CFS - understanding and mapping the subscription correctly.

First things first - you need to have a subscription that is going to hit Images collection. I'm not familiar with the latest CFS updates for their internal mapping but the following approach has usually worked for me.

Meteor.publish('post', function(_id) {
  var post = Posts.findOne({_id: _id});
  if(!post) return this.ready();
  return [
    Posts.find({_id: _id}),
    Images.find({_id: post.postImage})
  ]
});

For displaying, there is a handy CFSUI package( https://github.com/CollectionFS/Meteor-cfs-ui ) that provides some nice front end handlers.

With the above mapping your subscription, you can then do something like

{{#with FS.GetFile "images" post.postImage}}
  <img src="{{this.url store='thumbnails'}}" alt="">
{{/with}}
Flanamacca
  • 396
  • 2
  • 8