Nested lightning aura iteration - salesforce-lightning

I have a nested aura:iteration like this:
<aura:iteration items="{!v.results}" var="res">
<tr class="slds-hint-parent">
<aura:iteration items="{!v.ColumnsNameArr}" var="colName">
<td>
<div class="slds-truncate" >
{!res[colName]}}
</div>
</td>
</aura:iteration>
</tr>
</aura:iteration>
How can I write correct {!res[colName]}? It is possible to do something like this in lightning?

It looks like you want to iterate the res property, what looks like to me of type Map. In Lightning Aura it's not possible to iterate over a Map (Apex) / Object (Javascript).
What you can do as solution would be to transform the res Map to a type of Array (Javascript) or in Apex to type of a List.
In Lightning Aura it is possible to iterate Array's.
So how would that look like:
{
process: function() {
var res = { a: 1, b: 2};
var resArray = [];
for (var key in res) {
resArray.push({
key: key,
value: res[key]
});
}
// now, from here on you can use the 'resArray' to iterate in your Aura component
}
}

It is possible. Use the iteration variable at the next level down.
I think this will work...
<aura:iteration items="{!v.results}" var="res">
<tr class="slds-hint-parent">
<aura:iteration items="{!res.ColumnsNameArr}" var="colName">
<td>
<div class="slds-truncate" >
{!colName}}
</div>
</td>
</aura:iteration>
</tr>

Related

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.

Play framework templates: how to start a new row in a table?

I have list of objects, that I would like to render using Play Framework templates.
#(cats: List[Category])
#category(cat: Category) = {
<td><button class="btn btn-info">#cat.name</button></td>
}
<div class="modal-body">
<table class="table">
<tbody>
#cats.map { case cat =>
#category(cat)
}
</tbody>
</table>
</div>
So if I will have 9 elements in the list, they all will be in a single row.
What I want to have is a row with maximum of 3 elements. So it'll be like:
A B C
D E F
G H I
I thought I can zip my list with index list and set every third element as a new row. But I'm not sure how to do it.
Ideas?
Thanks.
You can group the list using grouped, it will return a list of lists:
scala> List(1,2,3,4,5,6).grouped(3).toList
res13: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6))
In your case should be like this:
#(cats: List[String])
#category(groupedCats: List[String]) = {
#groupedCats.map { cat =>
<td><button class="btn btn-info">#cat</button></td>
}
}
<div class="modal-body">
<table class="table">
<tbody>
#cats.grouped(3).toList.map { grouped =>
<tr>#category(grouped)</tr>
}
</tbody>
</table>
</div>
In this way you pass to the #category a list of 3 elements which is aready wrapped in a td tag.
Of course you can zipWithIndex and you don't need to group it, use module comparison instead:
<table>
<tr>
#for((cat, index) <- cats.zipWithIndex) {
<td>#cat</td>
#if((index+1) % 3 == 0){</tr><tr>} #* Close old row if has 3 elements and open new *#
}
</tr>
</table>

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.

How to handle one to many relation ship Knockout-Entity Framework

So I have I have a simple structure where one purchase have a collection of expenses, and each expense have an account(plastic, cash, plastic#2...).
So the json my api gets is similar to this:
[
{"$id":"1","Id":1,"Name":"apple","Value":100.0,"AccountId":1,"Account":
{"$id":"2","Id":1,"Name":"Cash"}},
{"$id":"3","Id":2,"Name":"pear","Value":50.0,"AccountId":1,"Account":
{"$ref":"2"}},
{"$id":"4","Id":3,"Name":"raspberry","Value":10.0,"AccountId":1,"Account":
{"$ref":"2"}}
]
I see my json is not writing my cash account each time it needs it, it is refering it with
{"$ref":"2"}
where
{"$id":"2","Id":1,"Name":"Cash"}
so when I render my table with this html:
<table>
<tbody data-bind="foreach: gastos">
<tr>
<td data-bind="text: $data.id"></td>
<td data-bind="text: $data.name"></td>
<td data-bind="text: $data.value"></td>
<td data-bind="text: $data.account.Name"></td>
<td>
<button type="button" class="btn btn-xs">
<i class="glyphicon glyphicon-trash"></i>
</button>
</td>
</tr>
</tbody>
</table>
I get this, because the account for pear, and raspberry are nulls:
So how do you handle $ref in knockout?
I am mapping to 'gastos' this way:
$.getJSON('#ViewBag.GastosUrl', function (data) {
data.forEach(function(o) {
gastos.push(new gastoVM(o.Id, o.Name, o.Value, o.Account));
});
});
var gastoVM = function(Id, Name, Value, Account) {
var self = this;
self.id = Id;
self.name = Name;
self.value = Value;
self.account = Account;
};
thanks.
I'm not familiar with entity-framework but with the data as provided, a couple options available (JSFiddle):
Build up the account information alongside the gastos. And only provide the $id or $ref for later referencing.
var vm = {
gastos: [],
accounts: {},
accountLookup: function(accountId){
return this.accounts[accountId];
}
}
//... inside AJAX call
var accountId = o.Account["$id"]
if(accountId)
{
vm.accounts[accountId] = o.Account;
}
Use a ko utility method to lookup the account from within your array.
accountLookupByUtil: function(accountId) {
var gasto = ko.utils.arrayFirst(this.gastos, function(item) {
if(item.account['$id'] == accountId)
{
return item
}
});
return gasto.account;
}
From the html:
<td data-bind="text: $root.accountLookup($data.accountId).Name"></td>
<td data-bind="text: $root.accountLookupByUtil($data.accountId).Name"></td>
Note: Both methods are available in the fiddle, thus some properties are provided that would not be necessary depending upon the method used.

LIFTWEB: How to render a simple table clicking a button?

I would like to display an HTML table clicking on a button.
This is what I've tried so far:
My SCALA code:
object Snippet {
def render = {
def showTable() = {
val table = <table border="1">
<caption>My Table</caption>
<thead>
<tr>
<td>Entry</td>
<td>Value1</td>
<td>Value2</td>
</tr>
</thead>
<tbody>
<tr>
<td>PREV</td>
<td>1</td>
<td>10</td>
</tr>
<tr>
<td>CURR</td>
<td>2</td>
<td>20</td>
</tr>
<tr>
<td>NEXT</td>
<td>3</td>
<td>30</td>
</tr>
</tbody>
</table>
SetHtml("table_div",table)
}
"#getTable" #> SHtml.button("Get Table", () => null, "onclick" -> "$('#msg_div').html('<span>Getting table...</span>')") &
"name=proc" #> SHtml.hidden(showTable)
}
}
And my HTML:
<div class="lift:Snippet.render">
<form>
<input type="hidden" name="proc"/>
<button id="getTable" value="Get Table" class="btn btn-inverse">Get Table</button>
</form>
<div id="msg_div"></div>
<div id="table_div"></div>
</div>
Nothing is displayed clicking the button.. Do you see what is the problem?
Or someone could tell me another way to do that?
I am not sure what you are looking to accomplish with the hidden input. Why not just do something like:
"#getTable" #> SHtml.ajaxButton("Get Table", showTable)
If you are looking to display a waiting indicator, Lift has a mechanism for setting the ajax loading animation. In Boot.scala:
//Show the spinny image when an Ajax call starts
LiftRules.ajaxStart =
Full(() => LiftRules.jsArtifacts.show("ajax-loader").cmd)
// Make the spinny image go away when it ends
LiftRules.ajaxEnd =
Full(() => LiftRules.jsArtifacts.hide("ajax-loader").cmd)
You can use any JsCmd instead to call your own function. I'd probably opt for that.
Totally agree with jcern. A slightly different way could also be:
"#getTable [onclick]" #> SHtml.ajaxInvoke(showTable)
(this way you won't override the original button name)
Also note that you don't even need to use the <form> tag -- you can delete it.