Meteor: Querying a collection based on a URL parameter - meteor

I am trying display the unique profile of a babysitter (i.e: babysitter username, city, postal code, etc ... ) from a schema/collection called "Babysitters" .
The URL correctly contains the babysitter unique _id, say:
http://localhost:3000/test/PqMviBpYAmTA2b5ec
but I don't manage to retrieve all the other fields.
meteor question - screenshot
I have tried querying the MongoDB in two files: routes.js and the template test.js
1) in routes.js
Router.route('/test/:_id', {
name: 'test',
data: function () {
return Babysitters.findOne({ _id: this.params._id });
}
});
2) in test.js
Template.test.helpers({
data: function () {
//sitterusername = this.params.sitterusername;
//console.log(this.params._id );
return Babysitters.findOne( { _id: this.params._id });
}
});
the html file: test.html
<template name="test">
{{#with data}}
<ul>
<li><img src="/" {{photourl}} height="100" width="100" ></li>
<li>Babysitter username: {{ sitterusername }}</li>
<li>Presentation: {{ presentation }}</li>
<li>City: {{ city }}</li>
<li>Postal Code: {{ postalcode }}</li>
<li>Mother tongue: {{ mothertongue }}</li>
<li>Languages spoken {{ languagesspoken }}</li>
<li>Experience {{ experience }}</li>
<li>Homework help: {{ homeworkhelpavailable }}</li>
<li>Hourly wages: {{ hourlywages }} €/h</li>
</ul>
{{/with}}
</template>
I have tried all sorts of ways but the Collection fields never appear in the HTML file.
Thanks for your help, a newbie here.
K.

Most likely you are not publishing all Babysitters to the client so your .findOne() returns nothing.
This is a common router pattern where you want to display a single document which is not normally published. A good way to solve this in i-r is to waitOn a subscription to the individual document:
waitOn: function(){
return Meteor.subscribe('oneBabysitter', this.params._id);
}
On the server, publish:
Meteor.publish('oneBabysitter',function(_id){
return Babysitters.find(_id);
});
Note that even though this publication is only going to return a single document you still have to do a .find() and not a .findOne() because publications need to return a cursor or array of cursors, not objects.

Related

Meteor with Blaze: My helper is not working with {{ #each }} loop

I am using Blaze with Meteor.
I have announcements_list.html
<template name="AnnouncementsList">
<div class="announcements">
<ul class="collection">
{{ #each announcements }}
{{ >announcementItem }}
{{ /each }}
</ul>
</div>
</template>
And announcements_list.js
Template.AnnouncementsList.helpers({
announcements: function() {
return Announcements.find({}, {sort: {createdAt: -1}});
}
});
If I remove the {{ each }} loop, i can read {{ >announcementItem }}. So I think the problem is the function in the helper. Help me please =.= ...
Is there an announcementItem in your Announcements db or are you trying to access data from a template? If the former, your blaze call should be {{announcementItem}}. In an #each, #unless or #with there is no arrow needed.
You are rendering the same template for every item in announcements. Where this template get data from? I would make something like this:
<template name="AnnouncementsList">
<div class="announcements">
<ul class="collection">
{{#each item in announcements}}
{{> announcementItem item}}
{{/each }}
</ul>
</div>
</template>
Then full item object will be accessible in your announcementItem through
Template.instance().data in helpers and events
this.data in onCreated and onRendered.

Pulling data from collection using Iron router

I have a small issue. The below code snippet works well if i directly dump it in the body tag
{{#each tasks}}
<ol> <li>Router Name: {{ routerName }}</li>
<li>Router Enable: {{Enable}}</li></ol>
{{/each}}
However, when I wrap it within a template and try call it via a route (iron router), it fails to show the query result.
<template name ='ManagementConfig'
{{#each tasks}}
<ol> <li>Router Name: {{ routerName }}</li>
<li>Router Enable: {{Enable}}</li></ol>
{{/each}}
</template>
Route.js:
Router.route('/ManagementConfig',{ name:'ManagementConfig' });
Everything apart from the above works well within the template and the route. Where am I going wrong?
Your ManagementConfig template don't have access to tasks object. You can fix this by creating a helper method and passing the data.
Template. ManagementConfig.helpers({
'tasks': function(){
//Change this to your task data
return Lists.find({}, {sort: {name: 1}});
}
});

Iron Router / Meteor - Post details with username in URL

I'm relatively new to Meteor (especially Iron Router), and have been stuck on the following issue...
I have a route which displays details about a single post:
this.route('singlePost',{
path:'/posts/:_id',
data:function(){
return Posts.findOne(this.params._id);
}
});
This works fine, but I'd like to be able to show the post owner's username in the URL, rather than the static "/posts/" path, ex:
this.route('singlePost',{
path:'/:username/:_id',
data:function(){
return Posts.findOne(this.params._id);
}
});
The post object includes the user Id of the owner, but not the username (username is in the Meteor.users collection).
When I try to set the route with 2 dynamic values (username, post Id), the pathFor link disappears (I assume because it cannot find "username" in the post object that is returned).
How can I get the route to recognize the username? I assume some lookup function to the Users collection but I'm not sure when/where. Also, how would I be able to validate the route to make sure the post is owned by the correct username?
Edit - here is the code:
router.js
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
waitOn:function(){
return Meteor.subscribe('posts') && Meteor.subscribe('users');
}
});
Router.map(function() {
this.route('home', {
path: '/',
data:function(){
Session.set('pageView','list');
return Posts.find();
}
});
this.route('singlePost',{
path:'/:username/:_id',
data:function(){
Session.set('pageView','single');
return Posts.findOne(this.params._id);
}
});
});
Router.onBeforeAction('loading');
home.html
<template name="home">
{{> postsList}}
</template>
posts_list.html
<template name="postsList">
<ul>
{{#each posts}}
{{> postBlock}}
{{/each}}
</ul>
</template>
single_post.html
<template name="singlePost">
{{> postBlock}}
</template>
post_block.html
<template name="postBlock">
{{#if pageView "list"}}
<li>
{{title}}<br/>
Author: {{username}}
</li>
{{/if}}
{{#if pageView "single"}}
<h1>{{title}}</h1>
<p>{{description}}</p>
<p>Author: {{username}}</p>
{{/if}}
</template>
post_block.js
Template.postBlock.helpers({
username:function(){
var user = getUserInfo(this.owner);
return user.username;
},
pageView:function(type){
return Session.get('pageView') == type;
}
});
functions.js
getUserInfo = function(id){
return Meteor.users.findOne(id);
}
The username outputs correctly on both the list and the details views, however I cannot get the pathFor link to include the username.
Looking at your template, you appear to be not passing username or id in {{pathFor 'singlePost'}}.
It should be {{pathFor 'singlePost' username=username _id=yourId}}
Your route should work then.

Handling duplicates in Twig templates

I have this code in my Twig template:
{% for entity in entities %}
<ul>
<li>{{ entity.getName }} | Editar - Eliminar
{{ render(controller('ProductBundle:DetailGroup:index', { 'parent_id': entity.getId })) }}
</li>
</ul>
{% endfor %}
<dl class="sub-nav">
<dd>Add new</dd>
</dl>
<script>
$(function() {
$("#detail_group_create").click(function() {
loadCenterLayout(Routing.generate('detail_group_new'));
});
});
</script>
Because I'm calling this {{ render(controller('ProductBundle:DetailGroup:index', { 'parent_id': entity.getId })) }} I get the Add new link twice. I don't want to create a new function to handle the same, how did yours deal with this? Any tips or advice?
If I understood you correctly, you want to have index with dynamic center part of the layout. You either have to have:
separate controller functions or
single controller function but some GET/POST parameter and big IF/ELSE branching.
In second case you must not rely on #Template annotation (in case you use them) but rather on manually calling appropriate template render based on which branch you're in.
Did I get your issue right?

How to set a Symfony2 path to Jeditable plugin

I'm trying to use Jeditable plugin for javascript. Here is the code (I took it from here):
In a .js file:
$('.edit').editable(function (value, settings) {
var data = {};
data[this.id] = value;
data["_token"] = "{{form._token.vars.value}}";
$.post("{{ path('edit_category', { 'id': cat.id}) }}", data);
return(value);
}, {
indicator:'Saving...',
tooltip:'Click to edit',
cancel:'Cancel',
submit:'Save'
});
This isn't working, it says that
No route found for "POST /{{ path('edit_category', { 'id': cat.id}) }}"
which I understand, because I have no idea how to pass the id parameter to the path (cat.id).
This is the way I'd do the edit only with Symfony in a template file:
<a href="{{ path('edit_category', { 'id': cat.id}) }}">
<i class="icon-pencil right-spacer"></i>
</a>
Any help will be appreciated! Thanks in advance!
The expression {{ path() }} is a twig expression, so it must be parsed by the twig template parser. Javascript files are usually not parsed.
You have some options on how to work around this. One idea is to inline your javascript code into your twig template. Of course that's not suitable for big code blocks and not very clean.
A better approach is to store the pathes in a variable in your layout twig template:
<script>
var token = "{{form._token.vars.value}}";
var path = "{{ path('edit_category', { 'id': cat.id}) }}";
</script>
In your js file, you only use the variables:
data["_token"] = token;
$.post(path, data);
Of course you might need to tweek that code if you have many pathes or variables.

Resources