0

I'm new to Meteor and trying to figure out this issue I have.

I'm trying to load data from the Lessons collection based on the route being passed. e.g if /courses/level1/lesson1/1a is passed then show data

Unfortunately this doesn't work.

Am I on the right path or is there a better way of doing this?

Collection

{
  "_id": "YSgr3fvjpEBn7ncRa",
  "courseId": "level1",
  "lesson": [
    {
      "lessonId": "lesson1",
      "freeLesson": true,
      "title": "Lesson 1",
      "eachLesson": [
        {
          "eachLessonId": "1a",
          "title": "This is (masculine)",
          "video": "839843"
        },
        {
          "eachLessonId": "1b",
          "title": "That is (masculine)",
          "video": "839843"
        },
        {
          "eachLessonId": "1c",
          "title": "This is (feminine)",
          "video": "839843"
        },
        {
          "eachLessonId": "1d",
          "title": "That is (feminine)",
          "video": "839843"
        },
        {
          "eachLessonId": "1e",
          "title": "Getting to know you",
          "video": "839843"
        }
      ]
    }
  ]
}

Routes

 Router.route("courses/:courseId/:lessonId/:eachLessonId", {
  path:"/courses/:courseId/:lessonId/:eachLessonId",
  layoutTemplate: "layoutLessons",
  template:"lessons",
  onBeforeAction:function(){
    var currentUser = Meteor.userId();
    if (currentUser) {
      Session.set('courseId', this.params.courseId);
      Session.set('lessonId', this.params.lessonId);
      Session.set('eachLessonId', this.params.eachLessonId);
      this.next();
     } else {
       Router.go('/')
     }
  },
});

Template helper

Template.lessons.onCreated(function(){
  Meteor.subscribe('listLessons');
});


Template.lessons.helpers({
  currentLesson: function() {
    var currentLesson = Session.get('eachLessonId');
    return Lessons.find({"lesson.eachLesson.eachLessonId" : currentLesson});
  },
});

HTML

{{#each currentLesson}}
  {{title}}
  {{video}}
{{/each}}

1 Answer 1

1

Instead of storing courseId, lessonId and eachLessonId as Session values, you could use the Iron Router's waitOn and data option.

For example, you could rewrite your route as follows:

Router.route('/courses/:courseId/:lessonId/:eachLessonId', {
  name: 'lessons',
  layoutTemplate: 'layoutLessons',
  template: 'lessons',
  onBeforeAction: function() {
    let currentUser = Meteor.user();
    if (currentUser) this.next();
    else Router.go('/');
  },
  data: function() {
    var doc = Lessons.findOne({
      "courseId": this.params.courseId,
      "lesson.lessonId": this.params.lessonId,
      "lesson.eachLesson.eachLessonId": this.params.eachLessonId
    });
    if (doc) {
      var lesson = {};
      var lessonId = this.params.eachLessonId;
      _.each(doc.lesson, function(i) {
        lesson = _.find(i.eachLesson, function(j) {
          return j.eachLessonId == lessonId;
        });
      });
      return lesson;
    }
    return {};
  },
  waitOn: function() {
    return [
      Meteor.subscribe('lesson', this.params.courseId, this.params.lessonId, this.params.eachLessonId)
    ];
  }
});

This should set the data context to the requested eachLesson object. However, you may consider setting the data context to a document in the Lessons collection and then just picking certain eachLesson objects. In addition, you should create a publish function which returns just the requested Lessons document and not all of them, like you probably do now in your listLessons publication. You can pass all IDs as arguments to the corresponding publish function.

Sign up to request clarification or add additional context in comments.

5 Comments

It works! :-) The only issue is that it is continuously loading after pulling in the data. So if I change waitOn to subscriptions: it loads the data and the loading text is still there and if I leave waitOn it loads no data and just keeps loading.
@user1400803 Okay, that's not good. Could you please check the server/client log?
@user1400803 Could you please post your publish function?
Using handlebars which calls {{title}} and {{video}} and I have Meteor.publish("Lessons", function(){ return Lessons.find(); }); in the server.
I've removed the waitOn and it works without loading. I guess because all lessons are already published it loads them on call. A better way would be as you said, load the lessons on demand with a publish function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.