Handlebars lookup in array - json

I have JSON object:
{
groups: [
{id: 1, title: "group1"},
{id: 2, title: "group2"},
],
users: [
{id:1, login: "user1", groupId: 1},
{id:2, login: "user2", groupId: 2},
{id:3, login: "user3", groupId: 1}
]
}
and handlebars template:
{{#each users}}
<tr data-id="{{id}}">
<td>{{login}}</td>
<td data-id="{{groupId}}">{{lookup ../groups groupId}}{{title}}</td>
</tr>
{{/each}}
but it is not working. Template compile and table render, but table group column contains only id as attribute of td tag. How to render title of group inside td tag (it is possible with handlebars using this JSON object)?

The lookup helper only looks up by array index, not but an id, but you can whip up a helper to do that:
Handlebars.registerHelper('lookup2', function(collection, id) {
var collectionLength = collection.length;
for (var i = 0; i < collectionLength; i++) {
if (collection[i].id === id) {
return collection[i];
}
}
return null;
});
Then you'll need to lookup the title from that object. Here I use #with to change context:
{{#each users}}
<tr data-id="{{id}}">
<td>{{login}}</td>
<td data-id="{{groupId}}">{{#with (lookup2 ../groups groupId)}}{{title}}{{/with}}</td>
</tr>
{{/each}}

Related

Accessing nested array in JSON response. Typescript-ReactJS

I have read some other questions with similar problem but I didn't figure out how to solve this. My code is writen a bit different and I don't know much Typescript, just started learning some months ago.
I built a backend where I expose an API. I can make a call to it and it returns:
{
"content": [
{
"id": 1,
"name": "Abantza",
"origin": {
"id": 2,
"name": "Brazil"
},
"meaning": "",
"gender": "FEMALE"
},
//more results....
I can render my table with the information of the first array (data as name, meaning, gender) but I can't print the origin.name info.
I have tried things like
<td>{nameData.origin[0]}</td>
{nameData.origin.map(x => (<td>{x.name}</td>))} without success.
My code in React is:
const Search = () => {
const [nameResponse, setNameResponse] = useState<NameResponse>();
useEffect(() => {
const params = {
page: 0,
linesPerPage: 12
}
makeRequest({ url: '/names', params })
.then(response => setNameResponse(response.data))
}, [])
return (
<div className="search-container">
<div className="search-result">
<h3 className="search-result-title">Search results</h3>
<table className="table table-striped table-hover table-sm" cellPadding="0" cellSpacing="0">
<thead className="thead-dark">
<tr>
<th>NAME</th>
<th>MEANING</th>
<th>GENDER</th>
<th>ORIGIN</th>
</tr>
</thead>
<tbody>
{nameResponse?.content.map(nameData => (
<tr key={nameData.id}>
<td>{nameData.name}</td>
<td>{nameData.meaning}</td>
<td>{nameData.gender}</td>
<td>ORIGIN</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)
}
console.log(nameResponse):
{content: Array(12), pageable: {…}, totalPages: 2, totalElements: 14, last: false, …}
content: Array(12)
0:
gender: "FEMALE"
id: 1
meaning: ""
name: "Abantza"
origin:
id: 2
name: "Brazil"
__proto__: Object
__proto__: Object
1: {id: 2, name: "Abarne", origin: {…}, meaning: "Ramos (es)", gender: "FEMALE"}
2: {id: 3, name: "Abauntza", origin: {…}, meaning: "", gender: "FEMALE"}
EDIT: add Name.ts :
export type NameResponse = {
content: NameData[],
totalPages: number
}
export type NameData = {
id: number,
name: string,
meaning: string,
gender: string,
origin: Origin[]
}
export type Origin = {
id: number,
name: string
}
As pointed by #str, the problem was that my definition of origin was wrong. Once changed from origin: Origin[] (array) to origin: Origin (object) it worked.
Once again thanks #str!

Trying to loop over an object using Moment JS

I have a section that pulls in data from an array and displays it and groups it by month. In order for it to show the date object I have to remove a layer from the JSON file.
It feels like I'm missing something something very small and just need to make a tiny change to loop over the data array. Can anyone point out what I'm doing wrong?
Here is the table that displays the data:
<table class="table" *ngFor="let month of transactions | keyvalue">
<tr>
<th>{{month.key}}</th>
</tr>
<tr>
<td>
<table class="table" *ngFor="let customer of month.value">
<tr>
<td>
{{customer}}
</td>
</tr>
</table>
</td>
</tr>
</table>
This is the component that groups the data:
export class AppComponent {
public transactions = {};
// Sample Data
customers = [
{
data: [
{
customer: {
name: "John"
},
// transaction_date: "2017-04-18"
transaction_date: "2019-9-22T13:56:11.971643+00:00"
},
{
customer: {
name: "Dick"
},
transaction_date: "2019-10-22T13:56:11.971643+00:00"
},
{
customer: {
name: "Harry"
},
transaction_date: "2019-7-22T13:56:11.971643+00:00"
},
{
customer: {
name: "John"
},
transaction_date: "2019-9-22T13:56:11.971643+00:00"
}
]
}
];
constructor() {}
ngOnInit() {
const monthName = item =>
moment(item.transaction_date, "YYYY-MM-DD").format("MMM");
// Establish groupBy array
this.transactions = _.chain(this.customers)
.groupBy(monthName)
.mapValues(items => _.map(items, "customer.name"))
.value();
const byMonth = _.chain(this.customers)
.groupBy(monthName)
.mapValues(items => _.map(items, "customer.name"))
.value();
console.log(byMonth);
return byMonth;
console.log(this.customers2);
}
}
If I format the Json differently it works, but I need it to work with the data [] array as well.
// Working Array
customers2 = [
{
customer: {
name: "John"
},
// transaction_date: "2017-04-18"
transaction_date: "2019-9-22T13:56:11.971643+00:00"
},
{
customer: {
name: "Dick"
},
transaction_date: "2019-10-22T13:56:11.971643+00:00"
},
{
customer: {
name: "Harry"
},
transaction_date: "2019-7-22T13:56:11.971643+00:00"
},
{
customer: {
name: "John"
},
transaction_date: "2019-9-22T13:56:11.971643+00:00"
}
];
Try this:
this.transactions = _.chain(this.customers[0].data)
const byMonth = _.chain(this.customers[0].data)
Working stackblitz.
UPDATE
Your customers member variable is an array with only one element.
That was the reason for adding [0] to access it.
You simply access the first element in an array like that. Array name and an index value (zero based).
Few more examples:
customers = []; // <-- simple array
customers = [{}]; // <-- simple array with one object in it
How to access it?
customers[0] // <-- first element
Your case:
customers = [{ data: [] }]; // <-- simple array with one object in it with a property "data" which is another array.
How to access it?
customers[0].data // <-- the solution

How to convert a <table> from column into row when mapping a JSON object using React?

In React 16.11.0, I used map() function for a simple JSON object to access the values of each elements. When ReactDOM renders the content, the table will display a list of values in column for each elements of data:
const data = [
{ Name: "Jame", Email: "jame123#gmail.com", ID: "1568132456", City: "New York" },
{ Name: "Harris", Email: "harris456#yahoo.com", ID: "7666487798", City: "Chicago" },
{ Name: "Daisy", Email: "daisy789#hotmail.com", ID: "2177897432", City: "Los Angeles" },
// etc...
];
const Table = ({data}) => {
const head = (
<tr>
<th>Name</th>
<th>Email</th>
<th>ID</th>
<th>City</th>
</tr>
);
const body = data.map(element => (
<tr key={element.ID}>
<td>{element.Name}</td>
<td>{element.Email}</td>
<td>{element.ID}</td>
<td>{element.City}</td>
</tr>
));
return (
<table>
<thead>{head}</thead>
<tbody>{body}</tbody>
</table>
);
};
ReactDOM.render(<Table data={data}/>, document.querySelector('div'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div></div>
The table output will display these values below:
Instead, what I want is the values will be displayed in row for each elements like this table below:
How to convert the table in this case?
create rules for each row and loop on these rows, then on your data:
const data = [
{ Name: "Jame", Email: 'jame123#gmail.com', ID: "1568132456", City: "New York" },
{ Name: "Harris", Email: 'harris456#gmail.com', ID: "7666487798", City: "Chicago" },
{ Name: "Daisy", Email: 'daisy789#gmail.com', ID: "2177897432", City: "Los Angeles" },
// etc...
];
const rows = [
{ name: 'Name', render: (item) => item.Name },
{ name: 'Email', render: (item) => item.Email },
{ name: 'ID', render: (item) => item.ID },
{ name: 'City', render: (item) => item.City },
];
const body = rows.map(({ name, render }) => (
<tr key={name}>
<td>{name}</td>
{data.map((item, i) => (
<td key={i}>{render(item)}</td>
))}
</tr>
));
const content = (
<div>
<table>
<tbody>{body}</tbody>
</table>
</div>
);
Try this code:
Object.keys(data[0]).forEach(key => (
<tr key={key}>
<td>{key}</td>
{data
.map(element => element[key])
.map(value => (
<td key={value}>{value}</td>
))}
</tr>
));
You probably want to find better keys for the second map, the one that generates td.

Dispaly JSON response from the server to handle bar templates in Ember CLI

My Json API from Server
I am getting this API response from server. How do I display the JSON in my template.
{
past_bills: [
{
id:1,
Status: "Success",
Count: 3,
Subscribers: [
{
SubscriberID: 100168,
Count: 3,
Invoices: [
{
InvoiceYear: "2014",
InvoiceMonth: "1",
Link: "https://invoices.test.com/A6034C05-C9BE-4A1A-9741-1E07B04F47BB/100168_3935_2014_02_invoice.pdf"
},
{
InvoiceYear: "2014",
InvoiceMonth: "2",
Link: "https://invoices.test.com/00168/5C00ABAE-524D-4D86-A927-610646CEB56E/100168_4799_2014_03_invoice.pdf"
},
{
InvoiceYear: "2014",
InvoiceMonth: "3",
Link: "https://invoices.test.com/100168/9533058F-2348-4D67-A1D3-187BC86CF40F/100168_6054_2014_04_invoice.pdf"
}
]
}
]
}
]
}
My Routes
export default Ember.Route.extend({
model: function(params) {
this.store.find('past-bill',params);
}
});
My Template
<table>
{{#each item in model}}
<tr><td>Hiii</td></tr>
{{/each}}
</table>
My Model File
import DS from 'ember-data';
export default DS.Model.extend({
Status: DS.attr(),
Count: DS.attr(),
Subscribers: DS.attr()
});
I want to display the response json to template. I tried but I am not getting the result in the template.
{{#each item in model}}
{{#each sub in item.Subscribers}}
{{#each invoice in sub.Invoices}}
<tr role="row">
<td>{{invoice.InvoiceMonth}}</td>
<td>{{invoice.InvoiceYear}}</td>
<td><a {{bind-attr href='invoice.Link'}} target="_blank">View Bill</a> {{!invoice.Link}}</td>
</tr>
{{/each}}
{{/each}}
{{/each}}

dynamic create json for treeview

I want to turn json
var treeNodes = [ {managerid:root,Employeeid:01},
{managerid:01,Employeeid:11},
{managerid:01,Employeeid:22},
{managerid:22,Employeeid:33},
{managerid:22,Employeeid:44}
];
into json like this using javascript.
json={
id:root,
children[{
id:01,
children[
{id:11},
{id:22}
]
children[
{id:33},
{id:44}
]
}
Can someone help with java script function?
First of all, your current JSON is incorrect:
var json = {
id: root,
children: [
{
id: 01,
children: [
{id: 11},
{id: 22}
]
},
{
children: [
{id: 33},
{id: 44}
]
}
]
};
Second, could you give more information about your table Employee?