Meteor: show each item from an array from mongo in separate list tag Meteor: show each item from an array from mongo in separate list tag mongodb mongodb

Meteor: show each item from an array from mongo in separate list tag


Courses.find(); returns a cursor and not an array. Use fetch() method instead:

Template.modalAddCollaborators.helpers({    'addedCollaborators': function () {        return Courses.find().fetch();            }});

In your template, create nested {{#each}} blocks with the first one iterating over the courses array and the next each block getting the canEditCourse array as the parameter. Inside the block, you can use this to reference the element being iterated over, something like the following for example:

<template name="modalAddCollaborators">    {{#each addedCollaborators}}        <h1>{{title}}</h1>        <ul class="list-group">        {{#each canEditCourse}}            <li class="list-group-item">{{this}}</li>        {{/each}}        </ul>    {{/each}}</template>


It looks like you are storing two types of values in the canEditCourse:

  • String - Meteor.userId
  • String - username

It may be good to store either the userId or the username, but perhaps not both.

UserID solution

In this approach, you store the User IDs in the canEditCourse array, and then use a collection helper to retrieve the username for display:

Courses.helpers({    "getCollaboratorUsernames": function () {        // Get collaborator IDs array        var userIds = this.canEditCourse;        // Get the users, using MongoDB '$in' operator        // https://docs.mongodb.org/v3.0/reference/operator/query/in/        var users = Meteor.users.find({_id: {$in: userIds}).fetch();        // placeholder array for usernames        var collaboratorUsernames = []        // Get username for each user, add it to usernames array        users.forEach(function (user) {            // Add current username to usernames array            collaboratorUsernames.push(user.profile.username);        });        return collaboratorUsernames;    }});

Also, it may be cleaner if the template helper were only to return the array of userIds, as opposed to a course object (Courses.find().fetch()).

Inputting UserIDs

You may choose a typeahead approach for inputting user IDs, similar to how courses are categorized in Crowducate.

Note: you will need a publication and subscription to make usernames/IDs available for the Selectize input.

Displaying Usernames

The other key component will be how to display the usernames as separate Boodstrap tag elements. You can iterate over the returned collaboratorUsernames array like so:

{{# each getCollaboratorUsernames }}    <span class="label label-info">{{ this }}</span>{{/ each }}

Note: make sure the course collaborator users are available via a publication/subscription:

In server code:

Meteor.publish('courseCollaborators', function (courseId) {    // Get the course object    var course = Courses.findOne(courseId);    // Get course collaborator IDs    var collaboratorIds = course.canEditCourse;    // Consider renaming the 'canEditCourse' field to 'collaboratorIds'    // Then, it would look like    // var courseCollaboratorIds = course.collaboratorIds;    // Or, you could even skip that, and the code would still be literate    // Get course collaborators    var collaborators = Meteor.users.find({_id: {$in: collaboratorIds}).fetch();    return collaborators;});

Then, in your template.created callback:

Template.modalAddCollaborators.created = function () {    // Get reference to template instance    var instance = this;    // Get reference to router    var route = Router.current();    // Get course ID from route    var courseId = route.params._id;    // Subscribe to Course Collaborators, template level    instance.subscribe("courseCollaborators", courseId);};

Be sure to wrap all of your code for creating the Selectize widget in an if (instance.subscriptionsReady()) {} block:

Template.modalAddCollaborators.rendered = function () {    // Get reference to template instance    var instance = this;    // Make sure subscriptions are ready before rendering Selectize     if (instance.subscriptionsReady()) {        // Get course collaborator usernames/IDs        // Render the Selectize widget            // User should see usernames            // UserID is saved to collection    }};