How to iterate over the current object in an array and only print the values in Handlebars? - handlebars.js

Consider this array :
var urls = [
{ alias : 'home',
path : '/page/home',
title: 'Home',
desc : 'simple test'
},
{ alias : 'home1',
path : '/page/home1',
title: 'Home1',
desc : 'simple test1'
},
{ alias : 'home2',
path : '/page/home2',
title: 'Home2',
desc : 'simple test2'
},
];
How can I iterate over all the properties inside an object in the array and print their values? I don't care about the names of the properties.
I would like to do someting like:
{{#urls}}
<tr>
{{#each .}}
<td>
{{value}}
</td>
{{/each}}
</tr>
{{/urls}}
And this would output
<tr><td>home</td><td>/page/home</td><td>Home</td><td>simple test</td></tr>
<tr><td>home1</td><td>/page/home1</td><td>Home1</td><td>simple test1</td></tr>
<tr><td>home2</td><td>/page/home2</td><td>Home2</td><td>simple test2</td></tr>
I don't want to type:
{{#urls}}
<tr>
<td>
{{alias}}
</td>
<td>
{{path}}
</td>
<td>
{{title}}
</td>
<td>
{{desc}}
</td>
</tr>
{{/urls}}
I might have more than 10 properties so I don't want to type their names anywhere I want to iterate over them.
My problem is I don't know how to access the current object in iteration or pass it to a helper. Do you know how to do that in Handlebars?
I don't want to put the values in arrays instead because I still need to see the properties for debugging.

working jsFiddle
Helper:
Handlebars.registerHelper('renderUrl', function(urls) {
var dom = '';
urls.forEach(function (url) {
dom += '<tr>';
for(key in url) {
dom += '<td>' + url[key] + '</td>'
}
dom += '</tr>';
});
return new Handlebars.SafeString(dom);
});

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

get table column value of selected row in table asp.net in jQuery

I am working on asp.net mvc project.
I want to get the cell value from the selected row (row in which "Manage "button is clicked).
in this case value of userID.
<table width="100%" class="table table-striped table-bordered table-hover" id="dataTables-example">
<thead>
<tr>
<th width="45%">User ID</th>
<th width="45%">User Name</th>
<th width="5%">View</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.TypeList)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserId)
</td>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
<input id="Manage2" class="btn btn-primary" type="button" value="Manage" />
</td>
</tr>
}
</tbody>
I am calling jQuery click function and Ajax call and want to send the UserId value in data from selected row to the controller.
below is the jQuery ajax call,
<script type="text/javascript">
$(document).ready(function () {
$('#Manage2').click(function () {
//alert(1);
var url = '#Url.Action("ManageUserRole", "UserRoleCompany")';
$.ajax({
url: url,
data: { Id: '1' },
cache: false,
type: "POST",
success: function (data) {
$("#Data").html(data);
},
error: function (reponse) {
alert("error : " + reponse);
}
});
});
});
</script>
Below is the view screen shot,
You can actually store the UserId value with html 5 data attribute on the button itself.
Your current code has Id attribute value hard coded inside a loop, which will create more than one element with same Id value. That is invalid HTML!
Remove the Id and use a more generic selector to wire up the click event. Here I added another CSS class "manage" to the button.
<input data-userid="#item.UserId" class="btn btn-primary manage"
type="button" value="Manage" />
and now
$(document).ready(function () {
$('.manage').click(function () {
var id = $(this).data("userid");
alert(id);
// use id for your ajax call
});
});
You do not necessarily need to add the extra css class only to use that as the selector later. Since you are adding a data attribute, you may simply use that as well for your jQuery selector.
$(function () {
$('[data-userid]').click(function () {
var id = $(this).data("userid");
alert(id);
// use id
});
});
You have invalid html because of the duplicate id attributes in your button.
Remove the id="Manage2" and replace with a class name and data- attribute for the value
<input data-id="#item.UserId" class="btn btn-primary Manage2" type="button" value="Manage" />
Then in the script, get the value using
$('.Manage2').click(function () { // class selector
var id = $(this).data('id);
var url = '#Url.Action("ManageUserRole", "UserRoleCompany")';
$.ajax({
url: url,
data: { Id: id },
....
Alternatively you could use relative selectors
$('.Manage2').click(function () {
var id = $(this).closest('tr').children('td:first').text();
....

Display row number using {{#each}}

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

Get link from text input field and then open it with DalekJS

I have an issue where the link I need to traverse to using DalekJS that is not clickable, it is rather copy/pastable. How can I retrieve a value from an input field in the browser and then use it in a test.open() call?
<table>
<tbody>
<tr>
<td>Link 1</td>
<td><input type="text" value="http://example.com/link-1" class="start-link"></td>
</tr>
<tr>
<td>Link 2</td>
<td><input type="text" value="http://example.com/link-2" class="start-link"></td>
<tr>
</table>
In the example above I would like DalekJS to dynamically run test.open('http://example.com/link-1'); during the progression of my test.
module.exports = {
'A test case': function (test) {
test.open('http://example.com/example-from-above.html')
.open('http://example.com/link-1') //This is the link I'm trying to retrieve dynamically.
.screenshot('image.png')
.done();
}
}
How can I accomplish this?
DalekJS does not allow reading values of HTML element synchronously and using them in the test scripts. If you need to interact with the content of the testing page, the execute method may help.
You can try setting the window location by a function "executed in the browser":
module.exports = {
'A test case': function (test) {
test.open('http://example.com/example-from-above.html')
// Open the URL from the first input element value
.execute(function () {
var input = document.querySelectorAll('.start-link')[0];
location = input.value;
})
// Wait until the browser opens the page
.waitFor(function () {
return location.pathname.indexOf('link-1') > 0;
})
.screenshot('image.png')
.done();
}
}

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