ReactJs: How to handle empty array with map function inside render method - javascript

I m trying to print table with some JSON data, but I am not able to render empty array when I am using map method.
JSON DATA :
[{
"id": 6,
"firstname": "Sharon",
"lastname": "Jenkins",
"specialties": []
}, {
"id": 2,
"firstname": "Helen",
"lastname": "Leary",
"specialties": [{
"id": 1,
"name": "radiology"
}]
}, {
"id": 4,
"firstname": "Rafael",
"lastname": "Ortega",
"specialties": [{
"id": 2,
"name": "surgery"
}]
}, {
"id": 5,
"firstname": "Henry",
"lastname": "Stevens",
"specialties": [{
"id": 1,
"name": "radiology"
}]
}]
My Code :
{this.state.vets.map(vet =><tr><td>{vet.firstname}</td>
{
vet.specialties.map((subitem,i) => {
return <td>{subitem.name}</td> })}<td>EDIT</td><td id={vet.firstname}><div class="funkyradio">
Now I am getting the following error
As Sharon doesn't have a specialist, I need to print as N/A.
How can I check the specialities are empty and print N/A.

try rendering always the TD tag, like:
{
this.state.vets.map(vet =>
<tr>
<td>{vet.firstname}</td>
<td>
{vet.specialties.map((subitem,i) => {
return <span>{subitem.name}</span>
})}
</td>
<td>EDIT</td>
<td id={vet.firstname}>
<div class="funkyradio">

use conditional statment like this
{ this.state.vets.length > 0
? this.state.vets.map(()=>Your logic)
: <Your custom message/>
}

<table>
{dataJSON.map(({ id, firstname, lastname, specialties }) => {
return (
<tr>
<td> {`${firstname} ${lastname}`} </td>
<td> {specialties.map(specialty => specialty.name).join(",")} </td>
<td> <span> EDIT </span> </td>
</tr>
);
})}
</table>

Mainly for readability, instead of using the object property, I would create a separate function that will return the specialties, if any, otherwise N/A

Related

How To Loop Through An Array Object Of Unknown Properties In Angular

so I was finding it difficult phrasing the title of my question, what i want to do is loop through and array of objects but i dont know the property's of the object because its dynamic and coming from a db.
Below is an example of the array object:
[{
"id": 9,
"event_id": 13,
"details": {
"firstname": "Ralph",
"lastname": "Marvin",
"email_address": "ralphmarvin#email.com",
"phone_number": "0987654321"
}
}, {
"id": 10,
"event_id": 13,
"details": {
"firstname": "John",
"lastname": "X Doe",
"email_address": "john_x_doe120#xmail.com",
"phone_number": "0009876543"
}
}, {
"id": 11,
"event_id": 13,
"details": {
"firstname": "Wari",
"lastname": "Gumah",
"email_address": "gumahwarihanna#eeee.com",
"phone_number": "120029182765"
}
}]
I want to display the details part of the object in a table that looks like this:
firstname lastname email_address phone_number
and the values appropriately under each value.
An using Angular 8.
I just dont know how to use *ngFor to access properties i dont even know.
Is what am trying to do even possible, if yes then please show me how.
Thanks!.
You can iterate over object key/values as inner for loop with keyvalue pipe accessing details object.
Html:
<table>
<tr>
<th>Firstname</th>
<th>lastname</th>
<th>email_address</th>
<th>phone_number</th>
</tr>
<tr *ngFor="let listItem of yourList" >
<td *ngFor="let innerItem of listItem.details | keyvalue">
{{innerItem.value}
</td>
</tr>
</table>
populated list
yourList = [{
"id": 9,
"event_id": 13,
"details": {
"firstname": "Ralph",
"lastname": "Marvin",
"email_address": "ralphmarvin#email.com",
"phone_number": "0987654321"
}
}, {
"id": 10,
"event_id": 13,
"details": {
"firstname": "John",
"lastname": "X Doe",
"email_address": "john_x_doe120#xmail.com",
"phone_number": "0009876543"
}
}, {
"id": 11,
"event_id": 13,
"details": {
"firstname": "Wari",
"lastname": "Gumah",
"email_address": "gumahwarihanna#eeee.com",
"phone_number": "120029182765"
}
}]
you could implement some logic on a component to get a set of fields. it Would look in some way like this: (I assume that items come as #Input() to your component, but it could be another source)
#Input() items: Item[];
fields: Set<string>;
ngOnChanges(changes) {
if(!changes.items || !this.items) return;
this.fields= new Set(this.items.flatMap(item => Object.keys(item.details)))
}
and then in the template
<tr *ngFor="let item of items">
<td *ngFor="let field of fields">{{item.details[field]}}</td>
</tr>

Retrieve a value from json array response in angular 4

I'm able to get all users with their roles from the backend laravel.
This is the response.
{
"users": [
{
"id": 2,
"first_name": "user",
"last_name": "xyz",
"title": null,
"email": "user#gmail.com",
"phone_number": "***-***-****",
"phone_type": "home",
"inactive": 0,
"created_at": null,
"updated_at": null,
"is_verified": 0,
"roles": [
{
"id": 1,
"name": "Account User",
"pivot": {
"user_id": 2,
"role_id": 1
}
}
]
},
I'm retrieving the users data like this
in ts:
ngOnInit() {
this.http.get<User>('backend.url')
.subscribe(data => {
this.user = data;
console.log(data);
});
}
in html:
<tr *ngFor="let userData of user?.users; trackBy: userThumb">
<td>{{ userData?.first_name }}</td>
Now, I want to show the role name of the user in a frontend table.
How do I retrieve the roles->name in angular 4 from this users array?
look this:
<tr *ngFor="let userData of user?.users; trackBy: userThumb">
<td *ngFor="let role of userData ?.roles; > {{role ?.name}}</td>
</tr>

Dynamically adding column in table

I am trying to add new column dynamically in the table. I have below object which is returned in response from web service api. How can I display dynamic columns where myArray object is getting appended with many other fields (new columns)
$scope.myArray = [
{
"contacts": [
{
"id": "1",
"contact": {
"name": "Sam",
"Email": "ddd#co.com",
"PhoneNo": 2355
}
},
{
"id": "2",
"contact": {
"name": "John",
"Email": "test#co.com",
"PhoneNo": 2355
}
}
]
}
];
I have tried looking into the example provided in some of the answers in google. In my below JSFIDDLE, I am getting only the key name but not the values. How can I achieve both key and value using ng-repeat where the key names are dynamic.
angular.module('myApp', [])
.controller('myController', function($scope) {
$scope.myArray = [
{
"contacts": [
{
"id": "1",
"contact": {
"name": "Sam",
"Email": "ddd#co.com",
"PhoneNo": 2355
}
},
{
"id": "2",
"contact": {
"name": "John",
"Email": "test#co.com",
"PhoneNo": 2355
}
}
]
}
];
});
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.12/angular.min.js"></script>
<table ng-controller="myController" border="1">
<tr>
<th ng-repeat="(key, val) in myArray[0].contacts[0].contact">{{ key }}</th>
</tr>
<tr ng-repeat="row in myArray[0].contacts">
<td ng-repeat="(key, val) in row.contact">{{ val }}</td>
</tr>
</table>

Sorting is not working in ngTable when using nested json

I have created an application in angularjs with ngTable, The application is working fine but sorting is not working. My json structured is nested, but values are coming correctly with the table
Can anyone please tell me some solution for this
My code is as given below
JSFiddle
html
<div ng-controller="IndexCtrl">
<table border="1" ng-table="mytable">
<tbody ng-repeat="peop in peoples">
<tr ng-repeat="people in peop">
<td sortable="'id'" data-title="'Id'">{{people.id}}</td>
<td sortable="'desig'" data-title="'Desig'">{{people.desig}}</td>
<td sortable="'name'" data-title="'Name'">{{people.name}}</td>
<td sortable="'place'" data-title="'Place'">{{people.place}}</td>
</tr>
</tbody>
</table>
</div>
script
var app = angular.module('app', ['ngTable']);
app.controller('IndexCtrl', function ($scope, $filter, ngTableParams) {
$scope.peoples = {
"ime123": [{"id": 145,
"desig": "doctor",
"name": "Manu",
"place": "ABCD"
}],
"ime148": [{"id": 148,
"desig": "engineer",
"name": "John",
"place": "POLK"
},
{
"id": 150,
"desig": "scientist",
"name": "Mary",
"place": "USE"
}]
};
$scope.mytable = new ngTableParams({
sorting: {
name: 'desc'
}
}, {
getData: function($defer, params) {
$scope.peoples = $filter('orderBy')( $scope.peoples, params.orderBy());
$defer.resolve( $scope.peoples);
}
});
});
The way you work with nested array in ngtable is not suitable ,in your case you can make array one dim again and allow directive to groupping
html
<table border="1" ng-table="mytable">
<tbody ng-repeat="peop in $groups">
<tr ng-repeat="people in peop.data">
<td sortable="id" data-title="'Id'">{{people.id}}</td>
<td sortable="desig" data-title="'Desig'">{{people.desig}}</td>
<td sortable="name" data-title="'Name'">{{people.name}}</td>
<td sortable="place" data-title="'Place'">{{people.place}}</td>
</tr>
</tbody>
</table>
contoller
$scope.mytable = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
name: 'desc'
}
}, {
total: peoples.length,
groupBy:'group',
getData: function ($defer, params) {
peoples = $filter('orderBy')(peoples, params.orderBy());
$defer.resolve(peoples);
}
});
data
var peoples = [{
"id": 145,
"desig": "doctor",
"name": "Manu",
"place": "ABCD",
"group": "ime123" //for grouping
}, {
"id": 148,
"desig": "engineer",
"name": "John",
"place": "POLK",
"group": "ime148" //for grouping
}, {
"id": 150,
"desig": "scientist",
"name": "Mary",
"place": "USE",
"group": "ime148" //for grouping
}];
here almost working jsfiddle.
default desc not working yet (ver 0.3.1)

Unable to Bind Json to TreeTable Js using knockout.js

I am using the TreeTable plugin:
http://ludo.cubicphuse.nl/jquery-treetable/#examples
<table id="example-basic">
<thead>
<tr>
<th>Name</th> <th>Status</th> <th>id</th>
</tr>
</thead>
<tbody data-bind="foreach: TreeView">
<tr data-bind="attr: { 'data-tt-id': id ,'data-tt-parent-id': Parentid}">
<td data-bind="text: Name"></td>
<td data-bind="text: Status"></td>
<td data-bind="text: id"></td>
</tr>
</tbody>
</table>
<button type="button" name="test" onclick="test()"></button>
The below works if I HardCode as is and the result is shown as a nicely formatted TreeView.
ko.applyBindings({ TreeView: [{ "id": "1", "Parentid": null, "Name": "test1", "Status": "OK" }, { "id": "2", "Parentid": 1, "Name": "test2", "Status": "OK" }] }
But, I am getting the value from the server(put the value obtained from server in "str" variable) and doing the binding as below:
str = '[{ "id": "1", "Parentid": null, "Name": "parent1", "Status": "OK" }, { "id": "2", "Parentid": 1, "Name": "child1", "Status": "OK" }]',
json = JSON.stringify(eval("(" + str + ")")),
ko.applyBindings({ TreeView: json})
function reload() {
//ko.applyBindings({ TreeView: {} });
str = '[{ "id": "1", "Parentid": null, "Name": "parent1", "Status": "OK" }]'
json = JSON.parse(str),
ko.applyBindings({ TreeView: json})
I get the following error:
Error: Unable to parse bindings.
Message: ReferenceError: 'id' is undefined;
Bindings value: attr: { 'data-tt-id': id ,'data-tt-parent-id': Parentid}
Can someone please help. Thanks!
The Json object returned had to be converted to type string and then parsed. This resolved the above issue
New Issue:
I was just playing around with the treetable plugin. I wish to reload the data from server on button click(or ajax call every 5 sec). The data is duplicated.
You are stringifying the JSON instead of parsing it, and using eval() when you don't need it. Instead, just use JSON.parse().
var str = '[{ "id": "1", "Parentid": null, "Name": "parent1", "Status": "OK" }, { "id": "2", "Parentid": 1, "Name": "child1", "Status": "OK" }]';
var json = JSON.parse(str);
ko.applyBindings({ TreeView: json });

Categories