In my Meteor app, I am publishing:
ForeignVisaTypes = new Mongo.Collection("foreignVisaTypes");
if (Meteor.isServer) {
Meteor.publish("foreignVisaTypes", function () {
return ForeignVisaTypes.find();
});
}
...and subscribing to:
if (Meteor.isClient) {
Meteor.subscribe("foreignVisaTypes");
. . .
}
...a Collection which is populated with values.
However, this attempt to populate the select is failing:
<select name="selvisatype" id="selvisatype" title="Please select a visa type">
{{#each foreignVisaTypes}}
<option value={{value}}>{{display}}</option>
{{/each}}
</select>
Why is it failing?
It's not enough to subscribe to a collection. It will not be available directly in spacebars as a helper. So you still need to define a helper to expose it.
Just add this to your client code and things should start working (replace myTemplate with the name of your template):
Template.myTemplate.helpers({
foreignVisaTypes: function() {
return ForeignVisaTypes.find();
}
});
Related
Main purpose of this code is, when we have data in database it should fetch and display on the browser. But i couldn't find it.
Problem is transferring data to the Server.
After running the meteor and enter some value from console of the browser,i am not able to see them back on the browser.But i am able to find them with in console by using the command "Tdos.find().fetch()",it is showing arrays that i have entered but if i am trying to find in mongodb console, we couldn't find it. Can Some one figure out my problem and where am i going wrong?
<head>
<title>simpletodos</title>
</head>
<body>
{{> todoList}}
</body>
<template name="todoList">
<h3>Todos</h3>
<ul>
{{#each tdos}}
{{> todo}}
{{/each}}
</ul>
<button class="add-todo">Add todo</button>
</template>
<template name="todo">
<li>
{{label}}
</li>
</template>
Client/Main.js
if(Meteor.isClient) {
Template.todoList.helpers({
todos: function() {
return Tdos.find();
}
});
if(Meteor.isServer) {
}
}
Server/main.js
import { Meteor } from 'meteor/meteor';
Tdos = new Mongo.Collection("tdos");
Meteor.startup(() => {
// code to run on server at startup
});
In your server, you define the collection like this:
Tdos = new Mongo.Collection("tdos");
Which means the collection in Mongo is todos, and you can list the contents with
db.todos.find()
You can insert a record in mongo using this:
db.todos.insert({label: "My first to do"})
In Meteor when you want to fetch or insert/update, you use Tdos, eg
Tdos.insert(...};
Your helper lets the data be available as an array within your code. I think you need to change that to be
todos: function() {
return Tdos.find().fetch();
}
I have a collection of People that has the fields {name, id}
I also have the field Likes that contains {user_id, foodName}
I want to create a template that will display a list of People, and the food they like. I am running an each in my template to pull all of this information from a query on the Likes collection. I want to take the queried user_id from Likes and then use it to pull the associated name of the person from the People collection.
My template looks like this:
<template name="likes">
{{#each likes_list}}
//This displays the user_id, but I want to have it display the user's name
<p>{{user_id}} likes {{foodName}}</p>
{{/each}}
</template>
My helper looks like this:
Template.likes.helpers({
likes_list: function() {
return Likes.find();
}
});
I see 2 solutions:
Add userName filed to your Likes collection and display it like
this {{userName}} in your template
Create publish function which will "join" your collections (Users and Likes). To do it use this package: https://atmospherejs.com/reywood/publish-composite
You can add a helper to return the user data context and then use it with with:
html:
<template name="likes">
{{#each likes_list}}
<p>{{#with person}}{{name}}{{/with}} likes {{foodName}}</p>
{{/each}}
</template>
js:
Template.likes.helpers({
likes_list: function() {
return Likes.find();
},
person: function(){
return People.findOne({id: this.user_id});
}
});
You could map it into a single object if you wanted to.
Template.blah.helpers({
likes: function () {
return Likes.find().map(function (doc) {
return _.extend(doc, {
user: Meteor.users.findOne(doc.user_id)
});
});
}
});
This will add the user field to the collection for you to reference
{{#each likes}}
{{user.name}} likes {{foodName}}
{{/each}}
I'm listing all the Meteor users in a template:
<template name="userList">
<ul>
{{#each users}}
<li>
{{_id}}<br>
Emails:
{{#each emails}}
{{address}},
{{/each}}
</li>
{{/each}}
</ul>
</template>
Here's my helper:
Template.userList.helpers({
users : function() {
return Meteor.users.find({});
}
});
This works, but since I'm not using usernames, I only want to list the first email address and not have to handle it with an {{#each}} in the template. Ideally, I'd have a value for users.primaryEmail, so I changed the helper to this:
Template.userList.helpers({
users : function() {
var rawUsers = Meteor.users.find({});
var users = [];
_.each(rawUsers, function(user) {
user.primaryEmail = user.emails[0].address;
users.push(user);
})
return users;
}
});
...and updated my template code to output {{primaryEmail}}, but it doesn't seem to return any users at all now. What am I missing?
Figured out that I needed to use .fetch() in order to get the results as an array & make users.emails[0] work:
var rawUsers = Meteor.users.find({}).fetch();
When I subscribe to a mongodb collection in the client and publish in the server whilst switch auto-publish off. Do I need to specify each individual find query I am declaring in my helper functions within the publish method? Or is it sufficient to just return Meteor.collection.find() in the Publish statement and that should give access to the entire collection?
Lost? Please see below
In my application I have 2 mongo collections setup. One Called 'Tables' and another called 'Rolls'.
In my client.js file I have two handlebars helper functions:
Template.tables.tableList = function(){
return Tables.find();
}
Template.tableBox.table = function(tableID){
return Rolls.find({"Roll.tableName": tableID}, {sort: {date: -1}, limit:10});
}
to correspond to my templates:
<template name="tables">
<div class="table-area">
{{#each tableList}}
{{> tableBox}}
{{/each}}
</div>
</template>
<template name="tableBox">
<table id="{{name}}" class="table table-condensed">
<tr class="n{{minBet}}">
<th>{{name}}</th>
<th> Min:</th>
<th>{{minBet}}</th>
<th>{{cPlayers}}</th>
</tr>
<tr>
<td>D1</td>
<td>D2</td>
<td>D3</td>
<td>Tot</td>
</tr>
{{#each table name}}
{{> tableRow}}
{{/each}}
</table>
</template>
<template name="tableRow">
<tr class={{rowColor Roll.dice1 Roll.dice2 Roll.dice3 Roll.total}} "bold">
<td>{{Roll.dice1}}</td>
<td>{{Roll.dice2}}</td>
<td>{{Roll.dice3}}</td>
<td>{{Roll.total}}</td>
</tr>
</template>
The first helper function returns all the Tables in the collection.
The 2nd returns the last 10 Rolls in descending order.
Using autopublish - everything works fine. My page shows all the tables and within each table the last 10 dicerolls.
When I switch autopublish off and try and setup corresponding subscribe/publish statements. It doesn't work. Only the Tables are shown - but the data from the Rolls collection is not populating my template.
Corresponding Subscribe and Publish Code:
In client.js:
Meteor.subscribe('tables');
Meteor.subscribe('rolls');
In server/publications.js:
Meteor.publish('tables', function() {
return Tables.find();
});
Meteor.publish('rolls', function() {
return Rolls.find();
});
My assumption is that it is to do with my slightly complicated query in my handlebars helper function for the rolls table? Is it not a simple subscribe to the whole collection (i.e. publish the return of Rolls.find()) and then be able to access all mongo query subsets that I define within my client? Is there something I'm missing here? Thanks for any help.
This seems like it is due to Rolls collection not being fully loaded on the client yet at the time you query for it. You can try something like:
Template.tables.tableList = function(){
return Tables.find();
}
Template.tableBox.table = function(tableID){
Deps.autorun(function () {
return Rolls.find({"Roll.tableName": tableID}, {sort: {date: -1}, limit:10});
});
}
The Deps.autorun(func) block runs the encapsulated function whenever the reactive dependencies change.
Running on Ubuntu
Data.js
//Collections
Database = new Meteor.Collection('data');
if (Meteor.isClient) {
Template.main.data = function () {
var c = Database.find();
return c;
};
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
data.html
<head>
<title>data</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
{{data}}
</template>
I inserted into the db using mongo:
> db.Database.insert({title: 'ShouldWork'});
> db.Database.find();
{ "_id" : ObjectId("5296403855ee6e1350b35afb"), "title" : "ShouldWork" }
Yet when I run the site it just returns [object Object]..
There should be autopublish on and insecure,
This has become quite the roadblock for me to clear in learning the framework.
This is expected. This is because the results of .find() are always a cursor and have multiple objects.
You have to decide which one you want or if you want to loop through each one.
1) You want to use one result:
var c = Database.findOne();
or 2) You want to iterate through each one:
{{#each data}}
{{title}}
{{/each}}
Additionally be sure to use the property of {{data}} because {{data}}, even with findOne is still an [Object object]. You should use something like {{data.title}} instead depending on the property you want to use.
How to access data in Mongo DB from html ?
First of all you need to have the Mongo DB instance present in global variable i:e it must be declared in any .js file as below. It is not part of client or server code
Say we create a Collection of Events in one of the js files.
EventList = new Mongo.Collection('Events');
Now, in order to access all the objects from HTML, we would need a Helper function inside client in our .js file. Below is Helper used:-
Template.viewEvent.helpers ({
//NOTE : 'event' is the name of variable from html template
'event' : function () {
//returns list of Objects for all Events
return EventList.find().fetch();
}
'users' : function () {
//returns reference to Document for all users
return UserList.find().fetch();
}
});
Just left to Display content on .html:-
Say EventList Collection has fields Event_Name, Event_Date. Below would be the html template code
<template name="viewEvent">
<h2>View Event</h2>
<!-- Iterate on all Objects fetched by the Helper Class-->
{{#each event}}
{{Event_Name}} : {{Event_Date}}
{{/each}}