How to evaluate object properties for Mongodb collection within child templates in Meteor? - mongodb

I am rendering table dynamically.
Templates are defined as below:
<template name="home">
<div class="row">
<div class="tblCSV">
<table class="table table-bordered table-hover table-striped">
<thead>
// Dynamic Header Row - Working
<tr>
{{#each columns}}
<th>
{{columnName}}
</th>
{{/each}}
</tr>
</thead>
// Dynamic Rows - Working
<tbody>
{{#each entries}}
{{> entry}}
{{/each}}
</tbody>
</table>
</div>
</div>
</template>
// if i try to iterate columns to print values per row, it prints field/column name instead it's value
<template name="entry">
<tr>
{{#each columns}}
// columnName is a mongodb field name, Not Working
<td>{{columnName}}</td> // This prints text of Column name itself instead its value
{{/each}}
</tr>
</template>
// If i use static column names, it prints all the column values perfectly
<template name="entry">
<tr>
<td>{{MyColumnName1}}</td> //This prints value of column name i.e. MyColumnValue
<td>{{MyColumnName2}}</td>
<td>{{MyColumnName3}}</td>
<td>{{MyColumnName4}}</td>
</tr>
</template>
Template Script
Template.home.helpers({
entries: function () {
return Entry.find();
},
columns: function () {
return Column.find();
}
});
Template.entry.helpers({
columns: function () {
return Column.find();
}
});
This is what the problem is
This is what i want
Feel free to ask for any information you need.

Related

use getByRole to select gridcell with particular description

I have some tabular data with the headers ('Type', 'Name'). I would like to select all items in column 'name', to check if they contain a search string. Each item in that column has the role 'gridcell', and the description 'Name'. See attached image1.
getByRole('gridcell', {description: /name/i}) doesn't work. I've looked through the typescript declarations of the queries and nothing seems helpful. How can one accomplish this?
Use getAllByRole('cell', {description: /name/i}) to retrieve an array containing the cells in column Name.
Check the array contains a certain value using toContain(item).
https://jestjs.io/docs/expect#tocontainitem
An example (using React):
'App.js'
function App() {
return (
<div className='App'>
<table>
<thead>
<tr>
<td id='name'>Name</td>
</tr>
</thead>
<tbody>
<tr>
<td aria-describedby='name'>J Blogs</td>
</tr>
<tr>
<td aria-describedby='name'>J Doe</td>
</tr>
<tr>
<td aria-describedby='name'>J Hancock</td>
</tr>
</tbody>
</table>
</div>
);
}
export default App;
'App.test.js'
import { render, screen } from '#testing-library/react';
import App from './App';
test('retrieves all cells described by name', () => {
render(<App />);
const cells = screen.getAllByRole('cell', {description: /name/i});
const cellValues = cells.map(cell => cell.textContent);
expect(cellValues).toContain('J Doe');
});

how can i parse html in flutter?

I am using Flutter and want to parse HTML using parser.dart
<div class="weather-item now"><!-- now -->
<span class="time">Now</span>
<div class="temp">19.8<span>℃</span>
<small>(23℃)</small>
</div>
<table>
<tr>
<th><i class="icon01" aria-label="true"></i></th>
<td>93%</td>
</tr>
<tr>
<th><i class="icon02" aria-label="true"></i></th>
<td>south 2.2km/h</td>
</tr>
<tr>
<th><i class="icon03" aria-label="true"></i></th>
<td>-</td>
</tr>
</table>
</div>
Using,
import 'package:html/parser.dart';
I want to get this data
Now,19.8,23,93%,south 2.2km/h
How can I do this?
Since you are using the html package, you can get the desired data like so using some html parsing and string processing (as needed), here is a dart sample, you can use the parseData function as is in your flutter application -
main.dart
import 'package:html/parser.dart' show parse;
main(List<String> args) {
parseData();
}
parseData(){
var document = parse("""
<div class="weather-item now"><!-- now -->
<span class="time">Now</span>
<div class="temp">19.8<span>℃</span>
<small>(23℃)</small>
</div>
<table>
<tr>
<th><i class="icon01" aria-label="true"></i></th>
<td>93%</td>
</tr>
<tr>
<th><i class="icon02" aria-label="true"></i></th>
<td>south 2.2km/h</td>
</tr>
<tr>
<th><i class="icon03" aria-label="true"></i></th>
<td>-</td>
</tr>
</table>
</div>
""");
//declaring a list of String to hold all the data.
List<String> data = [];
data.add(document.getElementsByClassName("time")[0].innerHtml);
//declaring variable for temp since we will be using it multiple places
var temp = document.getElementsByClassName("temp")[0];
data.add(temp.innerHtml.substring(0, temp.innerHtml.indexOf("<span>")));
data.add(temp.getElementsByTagName("small")[0].innerHtml.replaceAll(RegExp("[(|)|℃]"), ""));
//We can also do document.getElementsByTagName("td") but I am just being more specific here.
var rows = document.getElementsByTagName("table")[0].getElementsByTagName("td");
//Map elememt to its innerHtml, because we gonna need it.
//Iterate over all the table-data and store it in the data list
rows.map((e) => e.innerHtml).forEach((element) {
if(element != "-"){
data.add(element);
}
});
//print the data to console.
print(data);
}
Here's the sample output -
[Now, 19.8, 23, 93%, south 2.2km/h]
Hope it helps!
This article would probably be of help. It specifically uses the html package parser.
Following the example in the package's readme you can easily obtain a Document object. With this object you can obtain specific Elements of the DOM with methods like getElementById, getElementsByClassName, and getElementsByTagName. From there you can obtain the innerHtml of each Element that is returned and put together the output string you desire.

Accordion Bootstrap table with spacebars

I have seen questions pertaining to accordion but not entirely to my specific need. My table is populated using spacebars, more specific a nested each loop like this:
<tbody>
{{#each piece in pieces}}
<tr id="{{piece._id}}" class="itemList table-warning">
<th class="name tText">{{piece.name}} {{piece._id}}</th>
<td class="pdf tText" style="text-align: center"><a class ="pdf" href="{{piece.pdf}}" target="_blank"><i class="fa fa-file-text-o" aria-hidden="true"></i></a></td>
<td class="audio tText" style="text-align: center"><a class="audio" href="{{piece.audio}}" target="_blank"><i class="fa fa-volume-up" aria-hidden="true"></i></a></td>
<td class="format tText">{{piece.instrumentation}}</td>
<th class="price tText" >${{piece.price}}</th>
<td><input class ="qty" type ="number" name ="quantity" value="0" min="0"></td>
</tr>
<!-- Row that is being clicked-->
<tr class="partsList">
<td colspan="3"></td>
<th class="partName tText">{{piece.name}} Parts</th>
<td colspan="2"></td>
</tr>
{{#each part in piece.parts}}
<!-- Rows that should accordion -->
<!-- Currently ALL rows accordion on click. Need to accordion based on _id-->
<tr class="partList">
<td colspan="3"></td>
<td class="pname tText">{{piece.name}}: {{part.pname}}</td>
<td class="price tText">${{part.pprice}}</td>
<td><input class="qty" type="number" name="quantity" value="0" min="0"></td>
</tr>
{{/each}}
{{/each}}
</tbody>
I have a click function like so:
'click .partsList': function(e){
e.preventDefault();
$('.partList').nextUntil('tr.itemList').toggle();
}
The accordion function works, however it works with every instance of the each loop. i.e. every tr class ="partsList" will accordion at the same time on click.
To my understanding of the each loop, I can access the _id of a document using {{piece._id}}. If I set the table row id to equal that however, it only reads the _id of the FIRST document in the collection.
What I need is on click for the <tr class="partList"> to accordion based on _id. Or perhaps you would go about this a different way than bootstrap tables?
Please let me know if my question needs clarification.
You could filter the clicked .partslist using a data-* attribute. This causes jQuery to select only this specific items. Note that you need to attach the data-* attribute to the row that is clicked and to the rows that should collapse:
<tbody>
{{#each piece in pieces}}
...
<!-- Row that is being clicked-->
<!-- use the _id value of the piece context as data attribute -->
<tr class="partsList" data-id="{{piece._id}}">
<td colspan="3"></td>
<th class="partName tText">{{piece.name}} Parts</th>
<td colspan="2"></td>
</tr>
{{#each part in piece.parts}}
<!-- Rows that should accordion -->
<!-- Currently ALL rows accordion on click. Need to accordion based on _id-->
<!-- use the _id value of the piece context as data attribute -->
<tr class="partList" data-target="{{piece._id}}">
...
</tr>
{{/each}}
{{/each}}
</tbody>
'click .partsList': function(e, templateInstance){
e.preventDefault();
// get the data-id attribute of the clicked row
const targetId = templateInstance.$(e.currentTarget).data('id')
// skip if this row is not intended to toggle
if (!targetId) return
// toggle based on data-target attribute
templateInstance.$(`.partList[data-target="${targetId}"]`).nextUntil('tr.itemList').toggle();
}

Footable table timeout when row count is over 1000

I have tried to implement footable pluglin on an MVC application and it currently has 3000+ users which fail to load and the browser page times out. For the User Admin section I have created the following View:
#model IEnumerable<MyBudgetWeb.Models.ApplicationUser>
#{
ViewBag.Title = "Index";
}
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script type="text/javascript">
$(function () {
$('.footable').footable();
});
</script>
<br /><br />
<h2>Bill Pay Users</h2>
<input id="filter" type="text" placeholder="Filter" />
<br /><br />
#if (Model.Count() > 0)
{
<table class="table" data-filter="#filter" data-page-size="50">
<thead>
<tr>
<th data-type="numeric">Customer Number</th>
<th data-type="numeric">Account Name</th>
<th data-type="numeric" data-hide="phone">Go Live Date</th>
<th data-type="numeric" data-hide="phone">Online Live Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#item.CustomerNumber</td>
<td>#item.AccountName</td>
<td>#item.GoLiveDate</td>
<td>#item.OnlineCreationTimestamp</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#*#Html.ActionLink("Delete", "Delete", new { id = item.Id })*#
</td>
</tr>
}
</tbody>
<tfoot class="hide-if-no-paging">
<tr>
<td colspan="12" class="text-center">
<ul class="pagination"></ul>
</td>
</tr>
</tfoot>
</table>
}
else
{
<h2>You are still awaiting users to be added. All users will be displayed here.</h2>
}
My controller looks as follows:
public async Task<ActionResult> Index()
{
return View(await UserManager.Users.ToListAsync());
}
Is there any way workarounds to prevent this?
there are 2 option to solve:
1. PHP Side script, by setting the time limit of execution. Use this code on top your PHP script:
set_time_limit(0);
Use Footable AJAX what describe here:
http://fooplugins.github.io/FooTable/

Meteor Handlebars Passing Previous Context Parameter to next {{#Each}} helper block

Here are the templates in question:
<template name="tables">
<div class="table-area">
{{#each tableList}}
{{> tableBox}}
{{/each}}
</div>
</template>
<template name="tableBox">
<table id="{{name}}" class="table table-condensed table-striped">
<tr>
<td>{{name}}</td>
<td> Min:</td>
<td>{{minBet}}</td>
<td>{{cPlayers}}</td>
</tr>
<tr>
<td>Dice1</td>
<td>Dice2</td>
<td>Dice3</td>
<td>Total</td>
</tr>
{{#each table [{{name}}]}}
{{> tableRow}}
{{/each}}
</table>
</template>
<template name="tableRow">
<tr>
<td>{{Roll.dice1}}</td>
<td>{{Roll.dice2}}</td>
<td>{{Roll.dice3}}</td>
<td>{{Roll.total}}</td>
</tr>
</template>
And here are the Meteor Handlebars functions:
Template.tables.tableList = function(){
return Tables.find();
}
Template.tableBox.table = function(tableID){
return Rolls.find({tableName: tableID});
}
The problem is each table that is rendered on screen has all the 'Rolls' listed (All 100 lines). Instead of being filtered for the parameter I am trying to pass through to the Roll template function which is the table name {{name}}.
In the "table id" tag of TableBox, the {{name}} gets converted correctly. i.e. "T1", "T2", "T3" etc. But it's that same TableID that i need to pass to the function to filter from the db query properly. Is there a way to do this more simply? I would like to stick to the handlebars templating way of doing things here if possible.
For reference below is the JSON initialisation code for the test data:
//initiate tables
for (i = 1; i < 11; i++) {
Tables.insert({
name: 'T' + i,
minBet: '300',
cPlayers: '(8)'
});
}
//initiate rolls within tables
for (i = 1; i < 11; i++) {
for(j=1; j<11; j++){
var die1 = ((Math.floor(Math.random() * 5) +1).toString());
var die2 = ((Math.floor(Math.random() * 5) +1).toString());
var die3 = ((Math.floor(Math.random() * 5) +1).toString());
var t = (parseInt(die1) + parseInt(die2) + parseInt(die3)).toString();
Rolls.insert({
Roll: {
tableName: 'T' + i,
rollNumber: j;
dice1: die1,
dice2: die2,
dice3: die3,
total: t
},
});
}
}
Ok - After trial and error - figured it out:
In the helper function:
Template.tableBox.table = function(tableID){
return Rolls.find({"Roll.tableName": tableID});
}
I needed to add the nested Roll.tableName property name but within brackets as the query.
And back in the tableBox template:
<template name="tableBox">
<table id="{{name}}" class="table table-condensed table-striped">
<tr>
<td>{{name}}</td>
<td> Min:</td>
<td>{{minBet}}</td>
<td>{{cPlayers}}</td>
</tr>
<tr>
<td>Dice1</td>
<td>Dice2</td>
<td>Dice3</td>
<td>Total</td>
</tr>
{{#each table name}}
{{> tableRow}}
{{/each}}
</table>
</template>
No need for the curly braces for the 'Name' argument for the function. Somehow handlebars and Meteor recognise the context you are referring to without the curly braces and applies it like it is within {{name}} for the tableBox. I.e. "T1", "T2", "T3" are passed correctly to the function and now my unique tables only contain the list of rolls specific to individual tables.