Getting data from an array in an array with ReactJS - json

I'm very new to ReactJS but I think I'm making some headway ...
I think I'm almost there but I've fallen down at what I think is near enough my final hurdle ... here's what I'm trying to achieve;
TV Show - Simpsons
Name: Bart Simpson, Gender: Male
Name: Homer Simpson, Gender: Male
Name: Ned Flanders, Gender: Male
TV Show - Flintstones
Name: Fred Flintstone, Gender: Male
Name: Barney Rubble, Gender: Male
Name: Wilma Flintstone, Gender: Female
I could have hundreds of these so I don't want to just build these in two React elements - so I've organised my data as such which I'm happy with;
var shows = [
{
id: 1,
show: 'Simpsons',
characters: [
{ id: 1, name: 'Bart Simpson', gender: 'Male'},
{ id: 2, name: 'Homer Simpson', gender: 'Male'},
{ id: 3, name: 'Ned Flanders', gender: 'Male'}
]
},
{
id: 2,
show: 'Flintstones',
characters: [
{ id: 1, name: 'Fred Flintstone', gender: 'Male'},
{ id: 2, name: 'Barney Rubble', gender: 'Male'},
{ id: 3, name: 'Wilma Flintstone', gender: 'Female'}
]
}
];
And then I'm building my data with a table as such:
const ShowsTable = (props) => {
return (
<div>
<h1>Show - {props.show}</h1>
<table>
<tr>
<th>Name</th>
<th>Gender</th>
</tr>
<tr>
<td>XXX</td>
<td>YYY</td>
</tr>
</table>
</div>
);
};
I've got this 'working' where I can get the shows name and anything from the main array but I can't get the data from the nested 'characters' child array
So XXX and YYY is where I would like to get the data for the names or gender, in my mind I should be able to do something like ...
{props.characters}
Or maybe getting the nested elements so something like
{props.characters.props.name}
But I can't figure this out or find any documentation for this - so is this a syntax error or am I missing something more fundamental ... maybe I'm asking the wrong question? I'm really not sure
If someone can point me in the right direction with an explanation or some documentation I'd be very grateful :-)

You can do something like:
const ShowsTable = (props) => {
return (
<div>
<h1>Show - {props.show}</h1>
<table>
<tr>
<th>Name</th>
<th>Gender</th>
</tr>
{props.characters.map((char, index) => (
<tr key={index}>
<td>{char.name}</td>
<td>{char.gender}</td>
</tr>
))}
</table>
</div>
);
};

Related

How to display <td> value based on <th> value

I have three arrays which I have to display in the table. The three arrays are as follows:
let array1 = [
{id: 'p1', name: 'Adam', age: 27},
{id: 'p2', name: 'Jack', age: 20}
{id: 'p3', name: 'Jane', age: 21}
{id: 'p4', name: 'Rock', age: 23}
];
let array2 = [
{id: 'p3', occupation: 'Teacher', marital_status: 'Married'},
{id: 'p4', career: 'Wrestler', hobby: 'Gymming'}
];
let headers = [
{index: 1, name: 'id'},
{index: 2, name: 'name'},
{index: 3, name: 'age'},
{index: 4, name: 'occupation'},
{index: 5, name: 'marital_status'},
{index: 6, name: 'career'},
{index: 7, name: 'hobby'},
];
Now I want to display it inside the table. Here's what I've tried so far.
<table>
<thead>
<tr>
<th *ngFor="let head of headers">{{head?.name}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let person of array1; index as i">
<td>{{ person?.name ? person?.name : '-' }}</td>
<td>{{ person?.id }}</td>
<td>{{ person?.age }}</td>
<ng-container *ngFor="let header of headers">
<td *ngFor="let item of array2">
<ng-container *ngIf="header.name == item[header.name]">{{ item[header.name]}}</ng-container>
</td>
</ng-container>
</tr>
</tbody>
</table>
I want to display the data based on table header's (th) value
I think you're looking for a result like the one in this stackblitz. You needed to connect the ids between your arrays. The solution in this stackblitz is not a good one, however. You shouldn't put methods in your template as they will run an excessive amount due to change detection. I only created it this way to provide an example solution.
What I would recommend is combining array1 and array2 so that all of your elements have the extra fields in one object, instead of referencing two objects that share the same id. This is the simplest and most efficient solution. Alternatively, you could create a pipe that produces the correct result instead of using a method within the template.
create an unique array
//first create an objct with all the elements
const emptyObj=headers.reduce(a:any,b:any)=>({...a,b.name:''))
//then create an object using spread operator
arrayFull=this.array1.map(x=>{
const el=this.array2.find(y=>y.id==x.id)
return {...emptyObj,...x,...el}
})

implement search function (filter) in angular [Part 2]

I tried to import 'CommonModule' but it gives me the same error message. If, on the other hand, I try to write of between car and cars, it underlines the word filter as an error and displays me as an error:
no pipe found with name 'filter'. I need to implement a simple search function
<div *ngFor="let car in cars | filter : searchText">
I expected typing this statement the search method worked properly
Please find the attached code snippet with simple search function with given array :
app.component.html :
<div class="container text-center">
<h1>{{title}}</h1>
</div>
<div class="container">
<div class="row">
<div class="search-hero">
<input class="form-control" type="text" name="search" [(ngModel)]="searchText" autocomplete="off" placeholder=" Start searching for a hero by id or name or country">
</div>
<table class="table table-striped">
<thead>
<tr>
<th>Id</th>
<th>Hero Name</th>
<th>Country</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let hero of heroes | filter:searchText">
<td>{{hero.id}}</td>
<td>{{hero.name}}</td>
<td>{{hero.country}}</td>
</tr>
</tbody>
</table>
</div>
</div>
app.component.ts :
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
title = 'Angular Search Using ng2-search-filter';
searchText;
heroes = [
{ id: 11, name: 'Mr. Nice', country: 'India' },
{ id: 12, name: 'Narco' , country: 'USA'},
{ id: 13, name: 'Bombasto' , country: 'UK'},
{ id: 14, name: 'Celeritas' , country: 'Canada' },
{ id: 15, name: 'Magneta' , country: 'Russia'},
{ id: 16, name: 'RubberMan' , country: 'China'},
{ id: 17, name: 'Dynama' , country: 'Germany'},
{ id: 18, name: 'Dr IQ' , country: 'Hong Kong'},
{ id: 19, name: 'Magma' , country: 'South Africa'},
{ id: 20, name: 'Tornado' , country: 'Sri Lanka'}
];
}
Please find the working stackblitz example using ng2-search-filter here

How to display the value returned by avg function (mysql) in angular

After executing a query, I received the following data which is in Json format which is in myDocData:
data: [
RowDataPacket {
updatedAt: 2020-01-03T18:30:00.000Z,
email: 'charles#hotmail.com',
name: 'charles',
money_spent: 1,
'avg(e.money_spent)': 1
},
RowDataPacket {
updatedAt: 2020-01-11T18:30:00.000Z,
email: 'ank#gmail.com',
name: 'ank',
money_spent: 10,
'avg(e.money_spent)': 6
}
]
angular code:
<table class="content-table" >
<thead>
<tr>
<th>EMAIL</th>
<th>NAME</th>
<th>money spent</th>
<th>UPDATED</th>
<th>AVERAGE</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of myDocData">
<td>{{item.email}}</td>
<td>{{item.name}}</td>
<td>{{item.money_spent}}</td>
<td>{{item.updatedAt}}</td>
<td>{{item.avg(e.money_spent)}}</td>
</tr>
</tbody>
</table>
Issue is that I am unable to display the value given by avg function
(other attributes are displayed correctly).
Change the line:
<td>{{item.avg(e.money_spent)}}</td>
to:
<td>{{item['avg(e.money_spent)']}}</td>
In JS, you can use square bracket notation to get properties of objects.
If you have the control over the back-end code then you can change the query which is returning "avg(e.money_spent)" to "avg(e.money_spent) as avg_money_spent" in this way will not be facing the issue and you can access the value using
<td>{{item.avg_money_spent}}</td>
Or you could also use the previous answer by #Viqas

MVC Model List to AngularJs

I do have a Model that have studentID, firstName, LastName, PhotoURL and a list, I tried to bind the model to angularJs like this
var app = angular.module('StudentApp', []);
app.controller('StudentCtrl', function ($scope) {
$scope.model = #Html.Raw(Json.Encode(Model));
console.log($scope.model);
});
when i console.log
it showing me like this
Object {StudentID: 0, FirstName: null, LastName: null, PhotoURL: null, _StudentList: Array[5]}
FirstName: null LastName: null PhotoURL: null StudentID: 0 _StudentList:Array[5]
0: Object
FirstName: "John"
LastName: "Doe"
PhotoURL: "phone-wallpaper-1920x1200.jpg"
StudentID: 5
_StudentList: null__proto__:
1: Object
FirstName: "Ahri"
LastName: "Fox"
PhotoURL: "ahri-wallpaper-1920x1200.jpg"
StudentID: 6
_StudentList: null__proto__:
Object2:
Object3:
Object4:
It means that I got the data of five students, now i want to use ng-repeat and print those five student data
i tried like this
<table class="table" ng-app="StudentApp">
<tbody ng-controller="StudentCtrl">
<tr>
<th>Key</th>
<th>First Name</th>
<th>Last Name</th>
<th>Profile picture</th>
<th>Options</th>
</tr>
<tr ng-repeat="student in $scope.model._StudentList">
<td></td>
<td>{{student.FirstName}}</td>
<td>{{student.LastName}}</td>
</tr>
}
</tbody>
but its not working
wherever if i console log like this its working
console.log($scope.model._StudentList[0].FirstName);
console.log($scope.model._StudentList[0].LastName);
its printing John Doe
You should not use $scope in ng-repeat just make it model._StudentList then it will work .

ng-repeat on table column

So I have a List that I am returning from rest service. Now, I want to display this object in column format and now in row one. So it would be something like this:
firstName: Bob Alice
LastName: Doe Joe
EmailId: bob#xyz.com alice#abc.com
ContactNo: 123123 12444
So how can I use ng-repeat over here:
<tr>
<th>firstName:</th>
<td>('Name should be displayed here')</td>
</tr>
You can use ng-repeat on the td element.
<tr>
<th>firstName:</th>
<td ng-repeat="person in people">{{person.firstName}}</td>
</tr>
<tr>
<td ng-repeat="person in people">{{person.lastName}}</td>
</tr>
If you declare the keys of the objects you're iterating through, you can nest your ng-repeats so that you don't need to declare each row over and over. Do the following and nest them instead:
In the Angular App:
/*for the data*/
var personKeys = ['firstName', 'LastName', 'EmailID', 'ContactNo'];
var people = [
{
firstName: 'Bob',
LastName: 'Doe',
EmailID: 'bob#xyz.com',
ContactNo: 123123
},
/* etc */
];
/*don't forget to reference this in your controller with something like: */
this.pKeys = personKeys;
this.people = people;
In your HTML:
<table ng-controller='MyController as personList'>
<tr ng-repeat='key in personList.pKeys'>
<th>{{key}}</th>
<td ng-repeat='person in personList.people'>
{{person[key]}}
</td>
</tr>
</table>
This still has the problem of iterating over each person |attributes| times, instead of just once. I'm sure there is a clever way to only iterate once, memoize, and draw up the table without having to go through your entire data set many times, so that the runtime doesn't grow so quickly as you expand your data.