List all keys and values of blaze object - javascript

I have inserted this data in mongo
db.orders.insert( { _id: ObjectId().str, name: "admin", status: "online",catalog : [
{
"objectid" : ObjectId().str,
"message" : "sold",
"status" : "open"
}
]})
and i am accessing the data this way
<template name="Listed">
<div class="row">
{{#each list}}
<article class="post">
<h3>{{_id}}</h3>
<h3>{{name}}</h3>
<br>
<h3>{{status}}</h3>
<br>
{{#each catalog }}
<h3></h3>
<h3>{{status}}</h3>
{{/each}}
<div class="well"></div>
<br/>
</article>
<br/><br/>
{{/each}}
</div>
</template>
I am interested in knowing the key/value pair of the catalog object.
The reason for this,is because,i do not know the fields catalog has. For that,i registered a helper
Template.registerHelper("keyval",function(object){
return _.map(object, function(value, key) {
return {
key: key,
value: value
};
});
});
and used it this way
<template name="Listed">
<div class="row">
{{#each list}}
<article class="post">
<h3>{{_id}}</h3>
<h3>{{name}}</h3>
<br>
<h3>{{status}}</h3>
<br>
{{#each keyval catalog }}
<h3></h3>
<h3>{{key}}</h3>
<h3>{{value}}</h3>
{{/each}}
<div class="well"></div>
<br/>
</article>
<br/><br/>
{{/each}}
</div>
</template>
When i try to access the key like {{key}} i get 0,1,2... and {{value}} gives an object.
That is not what am looking for. How can i display the key value pairs correctly?.

You are producing an array of arrays (each catalog item maps to a list of key/value pairs). One solution is to iterate over each of the catalog items and then call keyval on it. The structure would look something like this:
{{#each item in catalog}}
{{#each keyval item}}
<h3>{{key}}</h3>
<h3>{{value}}</h3>
{{/each}}
{{/each}}

Related

using 'v-for' to output object to list

I have an object that get dynamically updated with various key/value, for the most part it will look like below:
object: {
parentKey1:{
childKey1:'value',
childKey2:'value'
},
parentKey2:{
childKey3:'value',
childKey4:'value'
}
}
I am then using 'v-for' in a list to export the object, like so:
<ul>
<li v-for="(value, key) in object">{{ key }} - {{ value }}</li>
</ul>
Now, it's displaying on the DOM generally how I want it, except that its printing out {} curly brackets around the values.
PARENT - { "CHILD": "VALUE" }
I'd like it to be:
PARENT - CHILD VALUE
Try this
new Vue({
el: '#app',
data: {
object: {
parentKey1: {
childKey1: 'value',
childKey2: 'value'
},
parentKey2: {
childKey3: 'value',
childKey4: 'value'
}
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<div id="app">
<div v-for="(value, key) in object">
{{key}} -
<span v-for="(cvalue, ckey) in value">
{{ ckey }} {{ cvalue }} {{' '}}
<span>
</div>
</div>
You need to provide a new nested iteration to do that.
<ul>
<li v-for="(parentValue, parentKey) in object">
<template v-for((childValue, childKey) in parentValue)>
{{ parentKey }} - {{ childKey }} {{ childValue }}
</template>
</li>
</ul>
Well the value is still an Array thats why it is displayed like that.
Maybe try
<ul>
<li v-for="(value, key) in object">{{ key }} - <span v-for="val in value">{{ val }}</span></li>
</ul>

for each item in array {{display item}}

I am trying to access the array values in my code so that I can use them but I am not sure how to. Thanks
var footerButtons = ['NO', 'EXTRA', 'YES'];
<template name="footer">
{{#each footerButtons}}
<h1>
<button class="col-xs-2 mainMenu" type="button">{{what should go here?}}</button>
</h1>
{{/each}}
</template>
You could define your footerButtons helper as follows -
Template.footer.helpers({
footerButtons() {
return [{text: 'NO'}, {text: 'EXTRA'}, {text: 'YES'}];
}
});
Then in your template, you can access the values as shown below.
<template name="footer">
{{#each footerButtons}}
<h1> <button class="col-xs-2 mainMenu" type="button">{{text}}</button> </h1>
{{/each}}
</template>
{{.}} or {{this}} is what you're looking for. This refers to the current object/element in an array.

to do list won't show data from collection that i ran trough filter

this is my code(i don't know where is the error for two days already.). And when I put .task and .Done helpers it won't show templates anymore. I know I have an error somewhere but I cannot pin point it for two days already. What I want is to pull tasks from database run them trough filter. Thank you in advance for your help.
<template name="Done">
<li>
<div>
<span class="text">{{title}}</span>
</div>
</li>
</template>
<template name="task">
<li>
<button class="completed">Completed</button>
<!--<li><input type="text" name="task" class="edit"></li>!-->
<span class="text" onclick="true">{{title}}</span>
<button class="saveItem">Save</button><button class="cancelItem">Cancel</button>
<button class="editItem">Edit</button><button class="delete">Delete</button>
</li>
<div>
<h1>To do list</h1>
<ul>
{{#each tasks}}
{{>task}}
{{/each}}
</ul>
</div>
<div>
<h1>Done list</h1>
<ul>
{{#each tasks}}
{{>Done}}
{{/each}}
</ul>
</div>
.js file
Meteor.subscribe("tasks");
Template.body.helpers({
tasks: function(){
return Tasks.find();
}});
Template.Done.helpers({
taskDone: function () {
return Tasks.find({}, {fields: {completed: "yes"}});
}
});
Template.task.helpers({
taskNotDone: function(){
return Tasks.find({completed: "no"});
}
});
Meteor.publish("tasks", function () {
return Tasks.find({});
});
First of all, I strongly recommend to store the completed field as Boolean values instead of String values. Secondly, the helper functions taskDone and taskNotDone should belong to the body template. In addition, the fields modifier is usually used to limit certain fields for publishing and not for querying documents.
For example, if you want to publish all tasks, minus the completed info, the publish function would look like this:
Meteor.publish("tasks", function () {
return Tasks.find({}, {fields: {completed: 0}});
});
Instead, if you want to return only Tasks documents which have been completed, you would have the following query:
Tasks.find({completed: true});
This code may fix your problem:
<body>
<div>
<h1>To do list</h1>
<ul>
{{#each tasksToDo}}
{{>task}}
{{/each}}
</ul>
</div>
<div>
<h1>Done list</h1>
<ul>
{{#each taskDone}}
{{>done}}
{{/each}}
</ul>
</div>
</body>
<template name="done">
<li>
<div>
<span class="text">{{title}}</span>
</div>
</li>
</template>
<template name="task">
<li>
<button class="completed">Completed</button>
<span class="text" onclick="true">{{title}}</span>
<button class="saveItem">Save</button>
<button class="cancelItem">Cancel</button>
<button class="editItem">Edit</button>
<button class="delete">Delete</button>
</li>
</template>
if (Meteor.isClient) {
Template.body.helpers({
tasksToDo: function() {
return Tasks.find({
completed: false
});
},
taskDone: function() {
return Tasks.find({
completed: true
});
}
});
}
Here's a MeteorPad.

Iterating over nested each statements in meteorjs (group by category)

I have a list of products, each of which has a category associated with it.
I am trying to list out the products grouped by category similar to this example but I cannot get it it to work. It just shows up a unique list of the categories but not the products
I have the following helper:
Template.supplierPage.helpers({
getCategories: function(){
var categories = Products.find({supplierId: this._id},
{sort:{category: 1}, fields: {category: 1}}).fetch();
return _.uniq( categories, true, function (product){
return product.category;
});
},
products: function(category) {
return Products.find({category: category, supplierId: this._id});
}
});
And the following template:
<template name="supplierPage">
<div class="ui dividing header">
<h3 class="ui header">My Products</h3>
</div>
<div>
{{> productCreate}}
{{#each getCategories}}
<h1>{{category}}</h1>
{{#each products.category}}
{{> productItem}}
{{/each}}
{{/each}}
</div>
Any help would be greatly appreciated. Thanks.
You almost got it right. You are just not providing the argument to the products helper in the right way. This should work:
<template name="supplierPage">
<div class="ui dividing header">
<h3 class="ui header">My Products</h3>
</div>
<div>
{{> productCreate}}
{{#each getCategories}}
<h1>{{category}}</h1>
{{#each products category ../_id}}
{{> productItem}}
{{/each}}
{{/each}}
</div>
You also need to fix your use of this in the products helper, because it changes when using #each. The easiest is to provide it as an additional argument as above:
products: function(category, supplier) {
return Products.find({category: category, supplierId: supplier});
}

Multiple loops fail in Handlebars.js

In my Handlebars template, I am trying to loop over the same data twice, but it fails on the second loop. This is how my template looks:
<div id="placeholder"></div>
<script type="text/x-handlebars" id="people-template">
First loop:<br />
<ul>
{{#.}}
<li>{{name}}</li>
{{/.}}
</ul>
Second loop:<br />
<ul>
{{#.}}
<li>{{name}}</li>
{{/.}}
</ul>
</script>
And this is the JavaScript:
var context= [
{ name: "John Doe", location: { city: "Chicago" } },
{ name: "Jane Doe", location: { city: "New York"} }
];
var template = Handlebars.compile($("#people-template").text());
var html = template(context);
$('#placeholder').html(html);
However, it does not render anything for the second loop:
First loop:
John Doe
Jane Doe
Second loop:
I created a jsFiddle for this here: http://jsfiddle.net/G83Pk/ and have even logged this in as a bug https://github.com/wycats/handlebars.js/issues/408. Does anyone know how to fix this or know what the problem is?
As far as I know, the correct way to iterate over an array is through a each block helper
Your template would be written as
<script type="text/x-handlebars" id="people-template">
First loop:<br />
<ul>
{{#each .}}
<li>{{name}}</li>
{{/each}}
</ul>
Second loop:<br />
<ul>
{{#each .}}
<li>{{name}}</li>
{{/each}}
</ul>
</script>
An updated Fiddle http://jsfiddle.net/nikoshr/G83Pk/1/
<div id="placeholder"></div>
<script id="people-template" type="text/x-handlebars">
First loop:<br />
<ul>
{{#each context}}
<li>{{name}}</li>
{{/each}}
</ul>
Second loop:<br />
<ul>
{{#each context}}
<li>{{name}}</li>
{{/each}}
</ul>
</script>
<script type="text/javascript">
var template = Handlebars.compile($("#people-template").html());
var json = {
"context": [
{ "name": "John Doe", "location": { "city": "Chicago" } },
{ "name": "Jane Doe", "location": { "city": "New York"} }
]
};
var html = template(json);
$('#placeholder').html(html);
</script>
You need to correct your iterator to use the each block helper. And your context variable is invalid input for the each iterator. The above code is the proper way to do what you want.
Not sure with the comments, but I encountered very strange behavior while having similar kind of scenario in my code.
{{#with xxxxx}}
{{#each models}}
{{#with attributes}}
{{value}} ---- Worked here
{{/with}}
{{/each}}
{{#each models}}
{{#with attributes}}
{{value}} ---- Didn't Worked here
{{/with}}
{{/each}}
{{/with}}
It worked with first loop but didnt worked with second loop. I did all scenarios at the ended with some strange solution. If I add any Html script or comment at the end of {{#each models}} of second loop, then second loop regains its context and display values properly.
So this worked flawlessly.
{{#with xxxxx}}
{{#each models}}
{{#with attributes}}
{{value}} ---- Worked here
{{/with}}
{{/each}}
{{#each models}} {{! Comment added }}
{{#with attributes}}
{{value}} ---- It works now.
{{/with}}
{{/each}}
{{/with}}

Categories