Search code examples
javascriptsessionmeteorcollectionsiron-router

Iron Router, Collection Helpers, and Session Variables. How to call an item attribute in a javascript function


I am working on a Meteor application and am trying to pass an attribute of an item in a collection to a javascript function. In this instance I working with instafeed.js, a javascript plugin for the instagram API, but I would like to understand the process on a more fundamental level.

I’ve been able to pull records from my Teams collection into the /teams/:id route, and display attributes of a team using the {{name}} and {{igHandle}} template helpers.

I have also been able to get instafeed.js to work, using this package etjana:instafeed and the demo provided online. The tag I am pulling is assigned statically via:Session.setDefault(‘tagName’,’football’); Eventually I would like to pull the user profiles, but that requires an access token from oauth2. I think that can be achieved with a {{$.Session.get access_token}} handlebar helper, but I need to figure out to feed a variable into the instafeed.js function first.

Could someone please explain how to pass the {{igHandle}} attribute through to the tagName in the javascript function. My code is as follows:

Team Template:

<template name="teamView">
    <div class=“ui container”>
        <h3>{{name}}</h3>
                <p>
            <i class="fa fa-instagram fa-lg"></i>
            <a target="_blank" href="http://instagram.com/{{insta_hndl}}">&nbsp{{insta_hndl}}</a>
            </p>
            <br>
            <h3>Instagrams</h3>
            {{> igTeamFeed}}
    </div>
</template>

Everything works, except the {{>igTeamFeed}} render. I am able to get content to show, but it is currently static. (assigned via (Session.setDefault('tagValue','football').

Instafeed Template:

<template name="igTeamFeed">
  <div class="ui container”>
    <h3>@{{insta_hndl}} Instagram</h3>
    <div id="instafeed"></div>
  </div>
</template>

Content is displaying, but again only through the static (Session.setDefault('tagValue','football') code.

Router:

Router.route('/teams/:_id', {
    name: 'teamView',
    template: 'teamView',
    data: function(){
        var currentTeam = this.params._id;
        return Teams.findOne({ _id: currentTeam });
    },
    action: function() {
        if (this.ready()) {
            this.render('teamView');
        } else {
            this.render('loading');
        }
    }
});

Works with template helpers, so I am thinking I am ok here. Also following the instructions of a user per one of my prior posts.

Instafeed Javascipt: (needs some work)

Template.igTeamFeed.helpers ({
  igData: function() {
    return Session.get('insta_hndl');
  },
});

Template.igTeamFeed.onRendered(function () {
    //clear any previously stored data making the call
    Session.get('insta_hndl'); //extra add-in
    Session.set('insta_hndl', null);
    Session.set('insta_hndl', this.data.insta_hndl); //extra add-in

    var igHandle = this.data.insta_hndl;

});

Tracker.autorun(function(){
    feed = new Instafeed({
        get: 'tagged',
        tagName: Session.get('insta_hndl'),
        clientId: ‘xxxxxxxxxxxxxxxxxxx’,
        resolution: 'thumbnail',
        sortBy: 'most-liked',
        limit: '15'
    });

    feed.run();
});
  • I have a helper to get the current insta_hndl for the session. The session item is passed through the team/:_id tag of the url, and defined in the router
  • The onRendered is wiping out the old handle, and inserting the new one. I added two additional Session.get and Session.set functions since I was getting an error that insta_hndl was undefined (differing from the response on my previous post). Could be wrong there.
  • The tracker.autorun function was code I had working with an instafeed example. Should it be somewhere else? Maybe in a helper or onRendered function? Also do I need tracker.autorun to use instafeed? To my understanding it dynamically updates the feed when a tagName changes, but aren't there other ways to do this?

How to Solve These are some ways I'm thinking I could to solve this. Please advise on how to do this / what you think is best practice:

  • Collection Helpers: Was thinking I could call something like Teams.findOne().insta_hndl but didn't have much luck. Is that the right code block to use? Do I have to define a variable in the template helper, or can I call it directly in the feed js function?
  • Handlebars Helpers: Thinking I could do something with a Session helper, but not sure if it would work if one user had two different instances of the instafeed open (two tabs open with different teams selected).
  • Reactive Methods: Allows one to call methods synchronously inside Tracker.autorun. Thought i read something that said Meteor already has this functionality baked in, but please advise.
  • Iron Router Query: Part of me still isn't convinced the insta_hndl isn't getting passed through. I've explored adding the instagram handle as a query param to the URL, but do not think this is a best practice.

If someone could help me get this working that woudld be great, but explanations would even better! Really spending a lot of time on this, and many of the online resources are using depreciated syntax.

Also two more related questions questions:

Should I use a controller? Should i write out a controller separately? Or just include it in Router.route functions? Seeing some people rely heavily on controllers, but a lot of documentation does everything through Router.route.

Should I break out the instafeed function into a method? If so how should I do this? I spent a great amount of time tryig to set up the whole instafeed function as a server side method, but couldn't seem to get it to work. I only foresee myself using this function in one or two other templates, so I figured it was fine to leave as is. Please advice.


Solution

  • Sorry that this was a bit confusing. The correct javascript is:

    Template.igTeamFeed.helpers ({
        teams: function() {
        return Teams.find();
      }
    });
    
    Template.igTeamFeed.onCreated( function() {
    
        var igHandle = Teams.findOne(Router.current().params._id).insta_hndl;
    
        feed = new Instafeed({
            get: 'tagged',
            tagName: Session.get('insta_hndl'),
            clientId: ‘xxxxxxxxxxxxxxxxxxx’,
            resolution: 'thumbnail',
            sortBy: 'most-liked',
            limit: '15'
        });
    
        feed.run(); //run the new Instafeed({})
    });
    

    There is no need for any of the things I suggested. The attribute can be grabbed with Collection.findOne(Router.current().params._id).attrib, where Collection is your collection and attrib is the non-_id value you want to grab.

    Also did not need tracker.autorun, that was throwing me off as well.