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.userIdString
- 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 }};