Meteor Display Child Array Elements #each - javascript

I'm trying to use Meteor's #each to display a JSON Object from Mongo with children. Say it looks like so:
{
data: {dorem: 'ipsum', dolor:'sit'},
amet: 'abcdefg'
}
Using #each, I currently have something like this
<template name="base">
{{#each stuff}}
{{> info}}
{{/each}}
</template>
The info template looks something like this
<template name="info">
{{data.dorem}}
</template>
The method I'm using to generate stuff is
Template.base.stuff = function () {
return DBThatHasStuffInIt.find({sort:{ _id : -1 }});
};
However, it is not working. Nothing is being displayed. The base template has been added, as well.
Does anybody know what the problem might be?

Your find, requires a selector:
return DBThatHasStuffInIt.find({}, {sort:{ _id : -1 }});

Related

Handlebars dynamic inline partial

I have a few lines of markup that I'd like to avoid keeping in an external partial file, but it should be rendered based on a variable value, either IN_PROCESS or DONE. I can make inline partials and render them based on static names:
{{#* inline "IN_PROCESS"}}IN_PROCESS{{/inline}}
{{#* inline "DONE"}}DONE{{/inline}}
{{> IN_PROCESS }}
{{> DONE }}
However I cannot figure out how to combine that with the () dynamic values syntax I have read about here.
So something like,
{{> (data.status) }}
└─────────┘ data.status would be either 'IN_PROCESS' or 'DONE'
Is this possible?
I believe you want something similar to this:
{{#* inline "IN_PROCESS"}}IN_PROCESS{{/inline}}
{{#* inline "DONE"}}DONE{{/inline}}
{{> (lookup . 'status')}}
{{> (lookup . 'status')}} will look through the JSON data object for its status attribute.
That is if you're passing your data in something like this:
var template = Handlebars.compile(**your source**);
$('body').append(template(data));
JSFiddle Example
The dot represents the data object that has been passed into the template function. The template function has no way of knowing what the object's name was:
template(inputData){
// This function wouldn't know that inputData.status was originally data.status
}
var data = {status: "DONE"};
template(data);
The dot is therefore used to tell "template" when searching for a parent that inputData should be the parent and we're looking for "status" as a child. I believe that is the use of it. I actually can't find any documentation regarding its use but all lookup's seem to be in the format lookup parent child so I assume that's the reasoning.

How Can i order a model?

I'm a newbie in ember and I don't know how to sort a list of movies by title.
I have a route index with a model hook:
export default Route.extend(RealtimeRouteMixin,{
model() {
return this.store.findAll('movie');
}
});
I render a component when this route is loaded. I set the model in the template
{{landing-page
add=(action 'addMovie')
movies=model
}}
Inside this component, there are other child's components. In one of them is a list of movie where I want to show the list of the movies sort by title.
//landing-page template
{{movie-list-header}}
{{movie-list
movies=this.movies
}}
{{add-movie-form add=this.add
}}
//movive-list template
{{#each movies as |movie|}}
{{movie-list/movie-list-item
movie=movie
}}
<hr />
{{/each}}
I don't know what the best approach to do it. I've thought to sort the model in the route but I don't know If I have to do it something like this
export default Route.extend(RealtimeRouteMixin,{
model() {
return this.store.findAll('movie').then(funcion(data){
// sort here ???
});
}
});
Your approach would work. Then sortBy would do the trick.
The other approach is to put it somewhere in your component hierarch starting with the controller. A simple computed property will do the trick. There is also a computed property macro.
I prefer to handle simple ordering in the template using ember-composable-helpers as it sorts strings well with the least amount of boilerplate. After installing that addon and restarting your ember server you can do this in your template with the sort-by helper.
//movie-list template
{{#each (sort-by "title" movies) as |movie|}}
{{movie-list/movie-list-item
movie=movie
}}
<hr />
{{/each}}
In the controller/component where your model you want to sort with property, you can mention following computed property:
sortedModel: sort('model', 'title:desc'),
you can import sort as follows:
import { sort } from '#ember/object/computed';
Now use sortedModel instead of model in templates/handlebars. I hope that make sense. Please let me know if you have any query?

Find all routes defined in Iron Router

Is there a way to add a site map dynamically for all paths which are defined in the Iron Router Router?
I'm thinking of something like this:
<ul>
{{#each paths}}
<li>{{route}}</li>
{{/each}}
</ul>
Also, maybe corresponding sub-paths which will be displayed in a child ul?
Obviously I could also just create the list manually, but for an app with 50+ links this is quite of a work.
Certainly! As Kassym noted, Router.routes contains a list of all the routes. However it contains the router functions, so you'll have to go and grab their names with route.getName(). The default route doesn't have a name, so you'll have to grab the .path() instead.
The whole thing should look like this in your helper:
Template.allRoutes.helpers({
paths: function () {
var allRoutes = _.map(Router.routes, function(route){
var routeName = typeof route.getName() === 'undefined' ?
route.path() :
route.getName();
return {route: routeName}
});
return allRoutes
}
});
And this in your template:
<template name="allRoutes">
{{#each paths}}
<li>{{route}}</li>
{{/each}}
</template>
Working Demo in MeteorPad
Note: Remember to enclose pathFor in curly brackets because it is a helper method. It will execute javascript and inherit the current datacontext, so you can pass it any property from the current context.
In order to display an sub paths of n depth, you can recursively call your template like this:
<template name="subpaths">
<ul>
{{#each subpaths}}
<li>
{{path}}
{{#if subpaths}} {{>subpaths}} {{/if}}
</li>
{{/each}}
</ul>
</template>
Demo in meteor pad
For more info, see getting the names of all routes for the accounts-entry package

In Meteor using #each, check if 'last' element in the collection reached

I'm iterating through a collection in Meteor using {{#each}} and I would like to know if I'm in the last element, as I can do in AngularJS while using ngRepeat with $last.
It could be used, for example to construct human readable enumerations like 'I like cats, dogs and dolphins' :
Template.myTemplate.helpers({
likedAnimals: function(){return ['dogs','cats','dolphins'];}
});
<template name='myTemplate'>
I like
{{#each likedAnimals}}
{{#if !$first && !$last}}, {{/if}}
{{#if $last}} and {{/if}}
{{this}}
{{/each}}
</template>
Is there any way to check this condition in Meteor?
If any of you are wondering how to do the same with collection cursors, there's a much simpler way thanks to handlebar-helpers package.
You could then use:
$mapped - will map $first, $last, and $index onto your cursor or array
combined with $last helper in your template like that:
{{#each $mapped myCursor}}
{{name}}{{#unless $last}},{{/unless}}
{{/each}}
PS: this also works with arrays
Using underscore.js :
Template.registerHelper('last',
function(list, elem) {
return _.last(list) === elem;
}
);
<template name='myTemplate'>
{{#each likedAnimals}}
{{#if last ../likedAnimals this}} I'm the last ! {{/if}}
{{/each}}
</template>
Worked with a reactive data source for me with meteor 1.1.0.1 (I don't know when Template.parentData() was introduced in meteor).
This isn't supported in meteor yet (version 1.0), but you can kind of add it yourself by doing something like this:
Template.myTemplate.helpers({
likedAnimals: function(){
var animals = ['dogs','cats','dolphins']
return animals.map(function(animal, index){
return {
name: animal,
isFirst: index==0,
isLast: index==animals.length-1
}
})
}
})
However, this does not play nice with reactivity (making it work properly with reactivity is much harder, which I guess is the reason why this isn't a built in feature yet), but if you return a simple array that's not dependent on any reactive data source, this should work fine.

Meteor set overall template context

In meteor I can set various template helpers like this:
Template.story.title = function () {
return "title";
};
<template name="story">
<h3>{{title}}</h3>
<p>{{description}}</p>
</template>
Which is great but, if I have a lot of variables I wouldn't want to set them individually, I want to pass the context to the main template.
How do I do that?
Template.story.data = function () {
return {title:"title", description:"desc"};
};
<template name="story">
<h3>{{title}}</h3>
<p>{{description}}</p>
</template>
That doesn't work. THanks
You can set the context of the template when you call it:
{{> story data}}
Template.outerTemplate.data = function() {
return {title:"title", description:"desc"};
}
Or you can just use {{#with}} to set the the template context on the fly:
{{#with data}}
{{title}}
{{/with}}
You are absolutely on the right way but missed to use your template variable the way you defined it. As Template.story.data is defined to return an object, you should use it like an object:
<template name="story">
<h3>{{data.title}}</h3>
<p>{{data.description}}</p>
</template>
Voilá. Of course every template variable can hold more than just a string.

Categories

Resources