0

I actually found this answer but I couldn't really get it.

So, I have this mongo collection, I want to link the image from the collectionFS to the proper parent document. How can I do it? Here's the code :

the declaration of the collections

    AccommodationList = new Mongo.Collection('accommodation');
    ImagesAcc = new FS.Collection("imagesacc", {
        stores: [new FS.Store.FileSystem("imagesacc", {path: "~/uploads"})]
    });

    if(Meteor.isClient){
        Template.accommodations.helpers({
            'accommodation': function(){
                return AccommodationList.find();
            }
        });
        Template.photopageaccommodation.helpers({
            imagesacc: ImagesAcc.find()

    });

    Template.photopageaccommodation.events({

        'dblclick .uploadedImage': function(e){
            var confirm = window.confirm("Etes-vous sur ??");
            if(confirm){
                ImagesAcc.remove({_id:this._id});
                Bert.alert('Vous venez de supprimer', 'warning', 'growl-top-right');
            }


        }

    });

    Template.photopageaccommodation.events({

        'change #accfile': function(event, template) {
            event.preventDefault();
            FS.Utility.eachFile(event, function(file) {
                ImagesAcc.insert(file, function (err, fileObj) {
                    //Inserted new doc with ID fileObj._id, and kicked off the data upload using HTTP
                });

            });
        }
    });

}

the submit form

Template.accommodations.events({
'submit #accommodation': function(){

    event.preventDefault();

    var accommodationNomVar = event.target.nom.value;
    var accommodationDescriptionVar = event.target.description.value;
    var accommodationTarifVar = event.target.tarif.value;
    var accommodationNbrEtoilesVar = event.target.nbretoiles.value;
    var accommodationTypeExcluVar = event.target.typeexclu.value;
    var accommodationTypeVar = event.target.type.value;
    var accommodationAddresseVar = event.target.addresse.value;
    var accommodationTelephoneVar = event.target.telephone.value;
    var accommodationEmailVar = event.target.email.value;

    AccommodationList.insert({
        nom: accommodationNomVar,
        description: accommodationDescriptionVar,
        tarif: accommodationTarifVar,
        nbretoiles: accommodationNbrEtoilesVar,
        typeexclu: accommodationTypeExcluVar,
        type: accommodationTypeVar,
        addresse: accommodationAddresseVar,
        email: accommodationEmailVar,
        telephone: accommodationTelephoneVar,

    });

    event.target.reset();
},

'click .delete': function(){
    var confirm = window.confirm("Etes-vous sur ??");
    if(confirm){
        AccommodationList.remove(this._id);
        Bert.alert('Vous venez de supprimer', 'warning', 'growl-top-right');
    }
},
});

here's the template

<template name="accommodations">
<div class="container-fluid">
    <div class="row">
        <div class="col-md-12">
            <form id="accommodation">
                <div class="row">
                    <div class="col-md-6">
                        <div class="form-group">
                            <label>Nom</label>
                            <input type="text" class="form-control" placeholder="Nom" name="nom">
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="form-group">
                            <label>Type</label>
                            <input type="text" class="form-control" placeholder="Type" name="type">
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-md-12">
                        <div class="form-group">
                            <label>Description</label>
                            <input type="text" class="form-control" placeholder="Description" name="description">
                        </div>
                    </div>
                    <div class="col-md-4">
                        <div class="form-group">
                            <label>Nombre d'etoiles</label>
                            <input type="number" class="form-control" placeholder="Nombre d'etoiles" name="nbretoiles">
                        </div>
                    </div>
                    <div class="col-md-4">
                        <div class="form-group">
                            <label>Type d'exclusivite</label>
                            <input type="text" class="form-control" placeholder="Type d'exclusivite" name="typeexclu">
                        </div>
                    </div>
                    <div class="col-md-4">
                        <div class="form-group">
                            <label>Tarif</label>
                            <input type="number" class="form-control" placeholder="Tarif" name="tarif">
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-md-5">
                        <div class="form-group">
                            <label>Telephone</label>
                            <input type="text" class="form-control" placeholder="Telephone" name="telephone">
                        </div>
                    </div>
                    <div class="col-md-5">
                        <div class="form-group">
                            <label>Email</label>
                            <input type="email" class="form-control" placeholder="Email" name="email">
                        </div>
                    </div>
                </div>

                <div class="row">
                    <div class="col-md-12">
                        <div class="form-group">
                            <label>Addresse</label>
                            <input type="text" class="form-control" placeholder="Addresse" name="addresse">
                        </div>
                    </div>
                </div>
                <div class="row">
                    <button type="submit" class="btn btn-info btn-fill pull-right">Ajouter</button>
                    <div class="clearfix"></div>
                </div>
            </form>
        </div>
    </div>
    <br>
</div>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-12">
            <div class="card">
                <div class="header">
                    <h4 class="title">Table des accommodations</h4>
                    <p class="category">Here is a subtitle for this table</p>
                </div>
                <div class="content table-responsive table-full-width">
                    <table class="table table-hover table-striped">
                        <thead>
                        <th>ID</th>
                        <th>Nom</th>
                        <th>Type</th>
                        <th>Description</th>
                        <th>Etoiles</th>
                        <th>Tarif</th>
                        <th>Telephone</th>
                        <th>Email</th>
                        <th>Adresse</th>


                        <th></th>
                        </thead>
                        <tbody>
                        {{#each accommodation}}
                            <tr>
                                <td>{{id}}</td>
                                <td>{{> editableText collection="accommodation" field="nom" eventType="dblclick"}}</td>
                                <td>{{> editableText collection="accommodation" field="type" eventType="dblclick"}}</td>
                                <td>{{> editableText collection="accommodation" field="description" eventType="dblclick"}}</td>
                                <td>{{> editableText collection="accommodation" field="nbretoiles" eventType="dblclick"}}</td>
                                <td>{{> editableText collection="accommodation" field="tarif" eventType="dblclick"}}</td>
                                <td>{{> editableText collection="accommodation" field="telephone" eventType="dblclick"}}</td>
                                <td>{{> editableText collection="accommodation" field="email" eventType="dblclick"}}</td>
                                <td>{{> editableText collection="accommodation" field="addresse" eventType="dblclick"}}</td>
                                <td><a class="delete"><a class="btn btn-danger"><i class="fa fa-trash"></i></a></a>
                                    <a href="photopageaccommodation"><a class="btn btn-gray"><i class="fa fa-camera"></i></a></a></td>
                            </tr>
                        {{/each}}
                        </tbody>
                    </table>

                </div>
            </div>
        </div>
    </div>
</div>

and here's the template where the image is actually loaded from and displayed

<template name="photopageaccommodation">
<style>
    .section-title h2 {
        display: inline-block;
        font-size: 30px;
        font-weight: 300;
        line-height: 30px;
        margin-bottom: 40px;
        padding-bottom: 10px;
        position: relative;
        text-transform: uppercase;
    }
    .section-title h2:before {
        position: absolute;
        background: #575757;
        height: 2px;
        width: 45px;
        content: "";
        bottom: 0;
    }
    .portfolio-menu button.mixitup-control-active {
        background: rgba(0, 0, 0, 0) none repeat scroll 0 0;
        border: 2px solid #4bcaff;
        color: #4bcaff;
        padding: 10px 15px;
        font-weight: 700;
        transition: .4s;
        text-transform: uppercase;
    }
    .portfolio-menu button {
        background: rgba(0, 0, 0, 0) none repeat scroll 0 0;
        border: 2px solid transparent;
        color: #515f67;
        padding: 10px 15px;
        font-weight: 700;
        text-transform: uppercase;
        cursor: pointer;
    }
    .single-portfolio a {
        display: block;
        line-height: 0;
        position: relative;
    }
    .single-portfolio a::before {
        background: #000 none repeat scroll 0 0;
        content: "";
        height: 100%;
        opacity: 0;
        position: absolute;
        top: 0;
        transform: scale(0.5);
        transition: all 0.3s ease 0s;
        width: 100%;
    }
    .single-portfolio:hover a::before {
        opacity: .5;
        transform: scale(1);
    }
    .single-portfolio a::after {
        color: #fff;
        content: "+";
        font-size: 60px;
        left: 0;
        position: absolute;
        right: 0;
        text-align: center;
        top: 50%;
        transform: scale(0);
        transition: all 0.3s ease 0s;
    }
    .single-portfolio:hover a::after {
        transform: scale(1);
    }
</style>
<script>
    $(document).ready(function() {
        // This will create a single gallery from all elements that have class "gallery-item"
        $('.gallery-item').magnificPopup({
            type: 'image',
            gallery:{
                enabled:true
            }
        });

        // MixItUp 2
        $('#container').mixItUp();
    });
</script>
<div class="wrapper">
    {{>sidebar}}
    <div class="main-panel">
        {{>navbar}}
        <div class="content">

                <div class="form-group">
                    <label>Photos</label>
                    <input type="file" multiple id="accfile" class="form-control">
                </div>
            <div>
            </div>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/magnific-popup.js/1.1.0/jquery.magnific-popup.min.js"></script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/mixitup/2.1.11/jquery.mixitup.min.js"></script>
            <div class="container">
                <div id="container" class="row">
                    {{#each imagesacc}}
                    <div class="col-md-4 mix category-a">
                        <div class="single-portfolio">
                            <div class="uploadedImage">
                            <!--<a class="gallery-item" href="{{this.url}}">-->
                                <img class="img-responsive" src="{{this.url}}" alt="One" />
                            <!--</a>-->
                            </div>
                        </div>
                    </div>
                    {{/each}}
                </div>
            </div>
        </div>
        {{>footer}}
    </div>
</div>

The thing is that this is working, but the problem is that the images I add are not linked to a specific document, I want for example, when looking at an accommodation, I want to see only the images of that hotel !

Thanks for helping !

Michel Floyd
  • 18,793
  • 4
  • 24
  • 39
Ous
  • 1
  • 1

1 Answers1

0

The _id of the inserted file is returned in the callback from the insert function. Where you now have:

FS.Utility.eachFile(event, function(file) {
  ImagesAcc.insert(file, function (err, fileObj) {
    //Inserted new doc with ID fileObj._id, and kicked off the data upload using HTTP         
  });
});

you need to have some actual code in the callback to save the image's _id to another collection as a reference.

For example, if your uploaded is running with the data context of an individual accommodation (so that this points to your current AccommodationList object), you can directly update that as follows:

FS.Utility.eachFile(event, function(file) {
  ImagesAcc.insert(file, function (err, fileObj) {
    if (!err) {
      console.log('The _id of the inserted Image is: '+fileObj._id);
      console.log('The _id of the current AccommodationList object is: '+this._id);
      AccommodationList.update(this._id,{ $set: { imageId: fileObj._id }});
    }      
  });
});

The console.log() statements are only there for you to verify how this is working. This pattern assumes that there's only one image for each accommodation. To find that one image given the _id aclistId of the parent AccommodationList object:

const imageId = AccommodationList.findOne(aclistId).imageId;
const image = ImagesAcc.findOne(imageId);

If you have a set of images then you can use $push instead:

AccommodationList.update(this._id,{ $push: { imageIds: fileObj._id }});

Then you have to find all matching images with $in::

const imageIds = AccommodationList.findOne(aclistId).imageIds;
const images = ImagesAcc.findOne({ _id: { $in: imageIds }});

Bonne chance!

Michel Floyd
  • 18,793
  • 4
  • 24
  • 39
  • Merci beaucoup Michel !! This is very helpful, but the thing is the image uploade isn’t done in the same data context, so I don’t know how to actually pass that info so that when I get redirected to the uploade page I actually get the id of the current object. And also I didn't understand what to do with the _aclistId_ or how I should define it. Finally, shoul the finding helper look like this : `Template.photopageaccommodation.helpers({ const: imageIds = AccommodationList.findOne(aclistId).imageIds, imagesacc: ImagesAcc.findOne({ _id: { $in: imageIds }}), });` – Ous Jun 29 '17 at 10:17
  • You can put the `_id` of the object that the images are to be attached to into a `Session` variable on the way to your upload page for example. Your helper doesn't look right. – Michel Floyd Jun 29 '17 at 17:27