Display row number using {{#each}} - meteor

I'm trying to count each row in a table. Each table row is a new collection. The code below counts the total number of collections and displays that. How do I change it to display the row number.
Path: calc.js
SalaryCalculator: function () {
return SalaryCalculator.find({});
},
SalaryCalculatorCount: function () {
return SalaryCalculator.find({}).count();
}
Path: calc.html
{{#each SalaryCalculator}}
<tr>
<th scope="row">{{SalaryCalculatorCount}}</th>
<td>{{specialisation}}</td>
<td>{{subSpecialisation}}</td>
<td>{{positionTitle}}</td>
<td>{{yearsOfExperience}}</td>
<td>{{salary}}</td>
</tr>
{{/each}}

Here's the helpers
SalaryCalculator: function () {
var count = 1;
var salCalDetails = SalaryCalculator.find({});
salCalDetails.forEach(function(doc){
doc.rowCount = count;
count++;
});
return salCalDetails;
},
{{#each SalaryCalculator}}
<tr>
<th scope="row">{{rowCount}} </th>
<td>{{specialisation}}</td>
<td>{{subSpecialisation}}</td>
<td>{{positionTitle}}</td>
<td>{{yearsOfExperience}}</td>
<td>{{salary}}</td>
</tr>
{{/each}}
Or if you follow through the answer given by #Michel Floyd then you need this answer too https://stackoverflow.com/a/22103990/3422755 as {{#index}} will give you starting number as 0

Related

Meteor - color highlight table row when date=today

i would like to highlight the date if match.datetime if equal to today, May I have some hints?
in .html
{{#each match in matches}}
<tr class="center aligned" bgcolor= "red">
<td>
{{match.datetime}}
</td>
</tr>
{{/each}}
in .js
Template.List_matches_page.helpers({
matches() {
return Matches.find({}, {sort: {datetime: -1}});
},
});
You can write a helper for that:
{{#each match in matches}}
<tr class="center aligned" bgcolor= "red">
<td class="{{#if isToday match.datetime}}color-bg{{/if}}">
{{match.datetime}}
</td>
</tr>
{{/each}}
const now = new Date()
const isToday = (date) =>
date.getFullYear() === now.getFullYear() &&
date.getMonth() === now.getMonth() &&
date.getDate() === now.getDate()
Template.List_matches_page.helpers({
matches() {
return Matches.find({}, {sort: {datetime: -1}});
},
isToday(date) {
return isToday(date)
}
});
If you have many places in your code, that require this check, you should rather use Template.registerHelper to avoid duplicate code in your templates: https://www.blazejs.org/api/templates.html#Template-registerHelper

Pipe/Ajax plugin smart-table is not working

I just taked the default example from
https://lorenzofox3.github.io/smart-table-website/#section-pipe
but it doesn't work, I code copied from the example, and assigned in the code the app: ng-app="myApp", and a controller: ng-controller="pipeCtrl as mc" to make it work, no errors shown in console
I also added some console.log prints, to know when the specific code lines are executed, and I see the next in console:
pushed it
ctr init
here is the code:
var app = angular.module('myApp', ['smart-table']);
app.controller('pipeCtrl', ['Resource', function (service) {
var ctrl = this;
console.log("ctr init");
this.displayed = [];
this.callServer = function callServer(tableState) {
console.log("callserv");
ctrl.isLoading = true;
var pagination = tableState.pagination;
var start = pagination.start || 0; // This is NOT the page number, but the index of item in the list that you want to use to display the table.
var number = pagination.number || 10; // Number of entries showed per page.
service.getPage(start, number, tableState).then(function (result) {
console.log("getP");
ctrl.displayed = result.data;
tableState.pagination.numberOfPages = result.numberOfPages;//set the number of pages so the pagination can update
ctrl.isLoading = false;
});
};
}]);
app.factory('Resource', ['$q', '$filter', '$timeout', function ($q, $filter, $timeout) {
var randomsItems = [];
function createRandomItem(id) {
var heroes = ['Batman', 'Superman', 'Robin', 'Thor', 'Hulk', 'Niki Larson', 'Stark', 'Bob Leponge'];
return {
id: id,
name: heroes[Math.floor(Math.random() * 7)],
age: Math.floor(Math.random() * 1000),
saved: Math.floor(Math.random() * 10000)
};
}
for (var i = 0; i < 1000; i++) {
randomsItems.push(createRandomItem(i));
}
console.log("pushed it");
//fake call to the server, normally this service would serialize table state to send it to the server (with query parameters for example) and parse the response
//in our case, it actually performs the logic which would happened in the server
function getPage(start, number, params) {
var deferred = $q.defer();
console.log("getting p svc");
var filtered = params.search.predicateObject ? $filter('filter')(randomsItems, params.search.predicateObject) : randomsItems;
if (params.sort.predicate) {
filtered = $filter('orderBy')(filtered, params.sort.predicate, params.sort.reverse);
}
var result = filtered.slice(start, start + number);
$timeout(function () {
console.log("timeout");
//note, the server passes the information about the data set size
deferred.resolve({
data: result,
numberOfPages: Math.ceil(filtered.length / number)
});
}, 1500);
return deferred.promise;
}
return {
getPage: getPage
};
}]);
The page html rendered in asp.net mvc:
#section scripts {
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/app1.js"></script>
<script src="~/Scripts/smart-table.js"></script>
}
<div class="row" ng-app="myApp">
<div class="col-md-12">
<h2>Smart Ajax Data Tables</h2>
<p ng-controller="pipeCtrl as mc">
<table class="table" st-pipe="mc.callServer" st-table="mc.displayed">
<thead>
<tr>
<th st-sort="id">id</th>
<th st-sort="name">name</th>
<th st-sort="age">age</th>
<th st-sort="saved">saved people</th>
</tr>
<tr>
<th><input st-search="id" /></th>
<th><input st-search="name" /></th>
<th><input st-search="age" /></th>
<th><input st-search="saved" /></th>
</tr>
</thead>
<tbody ng-show="!mc.isLoading">
<tr ng-repeat="row in mc.displayed">
<td>{{row.id}}</td>
<td>{{row.name}}</td>
<td>{{row.age}}</td>
<td>{{row.saved}}</td>
</tr>
</tbody>
<tbody ng-show="mc.isLoading">
<tr>
<td colspan="4" class="text-center">Loading ... </td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="text-center" st-pagination="" st-items-by-page="10" colspan="4"></td>
</tr>
</tfoot>
</table>
</p>
</div>
</div>

Meteor: Count data from collection

anyone please i need you help. before this I have asking question but I cannit find this solution. I have create code to count variable in collection. I can get the result when count one by one but not by group. Thats my code, I want to count this but the code not given any resut to me. I want the result like this:
PTR 1
KOM 4
This my code:
<template name="laporankategori">
<table class="table">
<thead>
<tr>
<th>Jenis Peralatan</th>
<th>Kuantiti</th>
</tr>
</thead>
<tbody>
{{#each profil}}
<tr>
<td>{{PTR}}</td>
<td>{{KOM}}</td>
</tr>
{{/each}}
</tbody>
</table>
</template>
//js
Template.laporankategori.helpers({
profil: function() {
return Profil.find({kategori: { $in: ['PTR', 'KOM'] } }).count();
}
});
<template name="laporankategori">
<table class="table">
<thead>
<tr>
<th>Jenis Peralatan</th>
<th>Kuantiti</th>
</tr>
</thead>
<tbody>
{{#each profil}}
<tr>
<td>{{count}}</td>
</tr>
{{/each}}
</tbody>
</table>
</template>
//js
Template.laporankategori.helpers({
profil: function() {
var PTR = {
count: Profil.find({kategori: { $in: ['PTR'] } }).count()
};
var KOM = {
count : Profil.find({kategori: { $in: ['KOM'] } }).count()
};
var resultArr = [PTR, KOM];
return resultArr;
}
});
Whenever you're iterating with {{#each ...}} your helper should return either a cursor or an array. Your helper is returning a scalar: the count. In your {{#each }} block you refer to {{PTR}} and {{KOM}} but those won't exist.
I suspect that you weren't actually looking for the count in this case and your helper should just be:
Template.laporankategori.helpers({
profil: function() {
return Profil.find({kategori: { $in: ['PTR', 'KOM'] } });
}
});
Also you don't often need to count things in a helper since in a template you can refer to {{profil.count}} and get the count of the cursor directly.

MeteorJS: Put date in dynamic template

WHAT I WANT TO BUILD IN DOM:
<table>
<tr> Today </tr>
<tr>
//data from Mongo
</tr>
...
<tr> Yesterday </tr>
....
//data from Mongo
..etc
</table>
CODE I HAVE :
<table>
{{#each posts}}
{{> postJobs}}
{{/each}}
</table>
<template name="postJobs">
<tr>
... // data from Mongo
</tr>
</template>
I think that it is necessary to compare the date from Mongo documents and today date or something like this.
Any idea how to build this ?
I guess you are requesting how to get the documents from collections grouped by date.
So on Top to see today chat, next block Yesterday, next block Previous Chats
Just call 3 times the same template
<template name="main">
<h1>Today</h1>
{{> list_posts posts=today}}
<h1>Yesterday</h1>
{{> list_posts posts=yesterday}}
<h1>Previous</h1>
{{> list_posts posts=previous}}
</template>
<template name="list_posts">
<table>
{{#each posts}}
<tr>
<td>{{col1}}</td>
<td>{{colX}}</td>
</tr>
{{/each}}
</table>
</template>
And then you need this helpers
Template.main.helpers({
today: function() {
return Posts.find() // col.date >= today
},
yesterday: function() {
return Posts.find() // col.date < today and >= yesterday
},
previous: function() {
return Posts.find() // col.date < yesterday
}
});
Good luck
Tom
I don't get what you exactly want to achieve. Comparing to today date would look like this, in an helper (that you can use in an {{#if compareDate}} statement:
compareDate: function(){
var today= new Date(new Date().getTime());
return this.date < today// it will get you true is the date field of your mongo document is older than today
}
Extra info, if you need yesterday:
var yesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000));

knockout.js how to bind dynamic css

Working on learning bootstrap and knockout.js. This is more of a knockout question.
I would like to populate a new row of a table (using addSeat function), and if the name field on that new row is empty, add the bootstrap 'error' class to the row. It is empty by default. Once the name field is entered, the style should change to 'success'.
The basic code is taken from the Seat Reservation samples. Here is the markup:
<div id="food" class="span10">
<h2>Your seat reservations (<span data-bind="text: seats().length"></span>)</h2>
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>Passenger name</th><th>Meal</th><th>Surcharge</th><th></th>
</tr></thead>
<tbody data-bind="foreach: seats">
<tr data-bind="css: isnameBlank">
<td><input data-bind="value: name" /></td>
<td><select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'"></select></td>
<td data-bind="text: formattedPrice"></td>
<td><i class="icon-remove"></i>Remove</td>
</tr>
</tbody>
</table>
<button data-bind="click: addSeat, enable: seats().length < 8">Reserve another seat</button>
<h3 data-bind="visible: totalSurcharge() > 0">
Total surcharge: $<span data-bind="text: totalSurcharge().toFixed(2)"></span>
</h3>
</div>
Here is the js file:
// Class to represent a row in the seat reservations grid
function SeatReservation(name, initialMeal) {
var self = this;
self.name = ko.observable(name);
self.meal = ko.observable(initialMeal);
self.formattedPrice = ko.computed(function () {
var price = self.meal().price;
return price ? "$" + price.toFixed(2) : "None";
});
self.isnameBlank = ko.computed(function () {
var ib = self.name().length;
console.log(ib);
return ib == 0 ? "warning" : "success";
}, self);
}
// Overall viewmodel for this screen, along with initial state
function ReservationsViewModel() {
var self = this;
// Non-editable catalog data - would come from the server
self.availableMeals = [
{ mealName: "Standard (sandwich)", price: 0 },
{ mealName: "Premium (lobster)", price: 34.95 },
{ mealName: "Ultimate (whole zebra)", price: 290 }
];
// Editable data
self.seats = ko.observableArray([
new SeatReservation("Steve", self.availableMeals[0]),
new SeatReservation("Bert", self.availableMeals[0])
]);
// Computed data
self.totalSurcharge = ko.computed(function () {
var total = 0;
for (var i = 0; i < self.seats().length; i++)
total += self.seats()[i].meal().price;
return total;
});
// Operations
self.addSeat = function () {
self.seats.push(new SeatReservation("", self.availableMeals[0]));
}
self.removeSeat = function (seat) { self.seats.remove(seat) }
}
ko.applyBindings(new ReservationsViewModel(), document.getElementById('food'));
When I run this the console logs the correct length (the ib variable), but the css class does not change.
Thank you for your help!
Where you have this line:
var ib = self.name.length;
You should be doing this:
var ib = self.name().length;
This seems to be working just fine when I test it in Chrome. Here is the jsFiddle:
http://jsfiddle.net/Xfv2g/
The only thing I can assume is that you are expecting it to change as they type. In order to do that you will have to change when the name field binds by putting the valueUpdate: 'afterkeydown' modifier to the value binding.
Here is the same fiddle with that being the only difference.
http://jsfiddle.net/Xfv2g/1/

Resources