Reorder Table columns Angular 8 - javascript

I have a table built in Angular 8. I am not using Material UI.
I want to reorder the columns in the table using JSON. Is there any way that could be done?
My Angular table code is like below:
<table>
<thead class="thead-light">
<tr>
<th *ngFor="let data of tableHeaders">
{{ data.value }}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of transactions ">
<td>{{ data.firstName }}</td>
<td>{{ data.regNo }}</td>
<td>{{ data.course }}</td>
</tr>
</tbody>
</table>
My tableheader json:
this.tableHeaders = [
{
"id": 'first_name',
"value":"Name",
},
{
"id": 'reg_no',
"value":"Reg No"
},
{
"id": 'course_name',
"value":"Course"
},
]
While I am able to change the order of the table headers by setting an id and sorting the array - tableHeaders, but how do I do the same for the td?
Any help would be appreciated.

You need to modify header and content's key to make it relate together something like
Full example: Stackblitz
.ts
this.tableHeaders = [
{
"id": 'first_name',
"value":"Name",
"key": "firstName"
},
{
"id": 'reg_no',
"value":"Reg No",
"key":"regNo"
},
{
"id": 'course_name',
"value":"Course",
"key": "course"
},
]
.html
<table>
<thead class="thead-light">
<tr>
<th *ngFor="let data of tableHeaders">
{{ data.value }}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of transactions">
<td *ngFor="let header of tableHeaders">
{{ data[header.key] }}
</td>
</tr>
</tbody>
</table>

Related

Displaying JSON data on condition using V-for and V-if in Vue.js

I am fetching data(Orders) from external Api in Vue using axios. I obtain JSON data and i am able to show it in a HTML table. Now i am trying filter the data to show only related data to use. In my Json data, i have a field called "order status: Completed / processing". Now i only want to show the json data which are have status like "Processing" to achieve my goal.
I am trying to use v-if with v-for but I m unable to get the certain orders data and view.
The table is set to update for each minute.
Here is my code:
html code
**<div class ="container mt-4" id="app">
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">Order id</th>
<th scope="col">Name</th>
<th scope="col">Order Date</th>
<th scope="col">Phone</th>
<th scope="col">Address</th>
<th scope="col">Items</th>
<th scope="col">Total</th>
<th scope="col">Print</th>
</tr>
</thead>
<tbody>
<tr
v-for="(order, index) in orders" v-if="order.status === "processing""
:key="order.id"
:class="{highlight: !order.is_printed}"
>
<td>{{ order.id }}</td>
<td>{{ order.billing.first_name + " " +order.billing.last_name }}</td>
<td>{{ order.date_created }}</td>
<td>{{ order.billing.phone}}</td>
<td>{{ order.billing.address_1 + ", " + order.billing.address_2 + ", " + order.billing.city + order.billing.postcode }}</td>
<td>{{ order.line_items[0].name}} </td>
<td>{{ order.total}}</td>
<td><button class="btn btn-primary" #click="printBill(order)">Print</button>
</tr>
</tbody>
</table>**
Vue
<script>
var app = new Vue({
el: '#app',
data: {
orders: []
},
mounted: function() {
// API Call function to be implemented here....
</script>
I think this should do the trick.
According to Vue documentation it's best to put any logic into computed properties https://v2.vuejs.org/v2/guide/computed.html
new Vue({
el: "#app",
data: {
orders: [
{ id: 1, status: "processing"},
{ id: 2, status: "other" }
]
},
computed: {
filteredOrders() {
return this.orders.filter(order => order.status === 'processing');
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<thead>
<tr>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
<tr v-for="order in filteredOrders" :key="order.id">
<td>{{ order.status }}</td>
</tr>
</tbody>
</table>
</div>
its better to filter data after you get them from api.
based on vue.js document it’s not recommended to use v-if and v-for together, read this:
https://v2.vuejs.org/v2/guide/list.html#v-for-with-v-if
try this
let filteredData = this.orders.filter(order => order.status === "processing")

Angular display table header only once and hide header if no data

I am using Angular 5.
When typeId is equal to 3, I would like to display table header only once.
And also when none of data’s typeId is equal to 3, I want to hide the whole table, do not show table header any more.
Please see my code and data below:
Code:
<table>
<ng-container *ngFor="let attachment of data.Data.Summary.Attachment">
<ng-container *ngIf="attachment.typeId=='3'">
<thead>
<tr>
<th>File</th>
<th>Description</th>
<th>Date</th>
</tr>
</thead>
</ng-container>
</ng-container>
<tbody>
<ng-container *ngFor="let attachment of data.Data.Summary.Attachment">
<tr *ngIf="attachment.typeId=='3'">
<td>{{ attachment.file }}</td>
<td>{{ attachment.description }}</td>
<td>{{ attachment.date }}</td>
</tr>
</ng-container>
</tbody>
</table>
Data:
{
"Data": {
"Summary": {
"Attachment": [
{
"typeId": "3",
"file": "a.pdf",
"description": "File A",
"date": "05/03/2017"
},
{
"typeId": "3",
"file": "b.pdf",
"description": "File B",
"date": "05/03/2017"
},
{
"typeId": "1",
"file": "c.pdf",
"description": "File C",
"date": "05/03/2017"
},
{
"typeId": "3",
"file": "d.pdf",
"description": "File D",
"date": "05/03/2017"
}
]
}
}
}
Result:
File Description Date
a.pdf File A 05/03/2017
b.pdf File B 05/03/2017
d.pdf File D 05/03/2017
Thank you in advance.
This isn't really an "angular" problem, more a javascript problem. In your component, you can create a method isHeaderVisible() which decides if the header should be visible or not and use that. Something like:
isHeaderVisible() {
return this.data.Data.Summary.Attachment.some(attachment => attachment.typeId === '3')
}
Separately, it'd probably be better to do your data filtering in your component, rather than your component's template. So do something like
visibleAttachments() {
return this.data.Data.Summary.Attachment.filter(attachment => attachment.typeId === '3')
}
Put them together and your template might look like:
<table>
<thead *ngIf="isHeaderVisible()">
<tr>
<th>File</th>
<th>Description</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let attachment of visibleAttachments()">
<td>{{ attachment.file }}</td>
<td>{{ attachment.description }}</td>
<td>{{ attachment.date }}</td>
</tr>
</tbody>
</table>
Or you could simply do <thead *ngIf="visibleAttachments().length > 0"> and get rid of isHeaderVisible(). And at this point, you might as well move the *ngIf to the <table> element instead of the <thead> element, because it sounds like you only want to display this table if an attachment with typeId === '3' exists.
So:
<table *ngIf="visibleAttachments().length > 0">
<thead>
<tr>
<th>File</th>
<th>Description</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let attachment of visibleAttachments()">
<td>{{ attachment.file }}</td>
<td>{{ attachment.description }}</td>
<td>{{ attachment.date }}</td>
</tr>
</tbody>
</table>

Can you populate a table with Angular.js without hardcoding column names?

I have a simple Angular.js application that grabs tabular data from a mysql database and shows it in a simple bootstrap table. I’m using this code below to show the table column names without hardcoding them individually…
HTML:
<table class="table">
<thead>
<tr style="background:lightgrey">
<th ng-repeat="column in columns"> {{ column }} </th>
</tr>
</thead>
and in the controller I create ’$scope.columns’ with something like this…
var columnNames = function(dat) {
var columns = Object.keys(dat[0]).filter(function(key) {
if (dat[0].hasOwnProperty(key) && typeof key == 'string') {
return key;
}
});
return columns;
};
DataFactory.getTables(function(data) {
$scope.columns = columnNames(data);
$scope.tables = data;
});
And this works as expected and it’s great, but what about the the rest of the data.. So for example, the body of my table currently looks like this…
HTML:
<tbody>
<tr ng-repeat="x in tables ">
<td> {{ x.id}} </td>
<td> {{ x.name }} </td>
<td> {{ x.email }} </td>
<td> {{ x.company }} </td>
</tbody>
I’ve tried using two loops like this…
HTML:
<tbody>
<tr ng-repeat="x in tables">
<td ng-repeat=“column in columns”> {{ x.column }} </td>
</tr>
</tbody>
But this code doesn’t work, So is it possible to populate a table with angular without hardcoding the column names in HTML, and if so whats the most efficient way to do so?
You might want to try this https://jsfiddle.net/8w2sbs6L/.
<div data-ng-app="APP">
<table ng-controller="myController" border=1>
<thead>
<tr>
<td ng-repeat="column in columns">{{column}}</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in tables">
<td ng-repeat="column in columns">{{x[column]}}</td>
</tr>
</tbody>
</table>
</div>
<script>
'use strict';
angular.module('APP', [])
.controller('myController', ['$scope', function($scope){
$scope.tables = [
{
"column1":"row1-column1",
"column2":"row1-column2",
"column3":"row1-column3",
"column4":"row1-column4"
},
{
"column1":"row2-column1",
"column2":"row2-column2",
"column3":"row2-column3",
"column4":"row2-column4"
}
];
$scope.columns = [
"column1",
"column2",
"column3",
"column4"
];
}]);
</script>

add multiple rows in one column using angular ng-repeat

I want to generate table contents using json object. I am using ng-repeat to insert multiple rows in a table. But I have to generate table like the following.
--------------
ID | subjects
--------------
| S1
1 | S2
| S3
--------------
| S4
2 | S5
| S6
--------------
my angular code is:
<tr ng-repeat = "user in users">
<td>{{user.id}}</td>
<td>{{user.subject}}</td>
</tr>
my json object is :
user:[
{id:1 ,
subjects:[
{id:1 , name:"eng"}
{id:2 , name:"phy"}
]
},
{id:2 ,
subjects:[
{id:1 , name:"eng"}
{id:3 , name:"math"}
]
}
]
I want to generate html table like this
<table>
<tr>
<td >ID</td>
<td>Sub</td>
</tr>
<tr>
<td rowspan="3">1</td>
<td>S1</td>
</tr>
<tr>
<td>S2</td>
</tr>
<tr>
<td>S3</td>
</tr>
how to insert multiple rows in one column using angular
Use ng-repeat-start and ng-repeat-end. For example:
<tr ng-repeat-start="user in users">
<td rowspan="{{user.subjects.length+1}}">{{user.id}}</td>
</tr>
<tr ng-repeat-end ng-repeat="subject in user.subjects">
<td>S{{subject.id}}</td>
</tr>
Here is a full example:
var app = angular.module('MyApp', []);
app.controller('MyController', function ($scope) {
var users = [{
id: 1,
subjects: [{
id: 1,
name: "eng"
}, {
id: 2,
name: "phy"
}]
}, {
id: 2,
subjects: [{
id: 1,
name: "eng"
}, {
id: 3,
name: "math"
}, {
id: 4,
name: "hist"
},
{
id: 5,
name: "geog"
}]
}];
$scope.users = users;
});
table { border-collapse: collapse; }
td { border: 1px solid Black; }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<table ng-app="MyApp" ng-controller="MyController">
<thead>
<tr>
<td>ID</td>
<td>Subjects</td>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="user in users">
<td rowspan="{{user.subjects.length+1}}">{{user.id}}</td>
</tr>
<tr ng-repeat-end ng-repeat="subject in user.subjects">
<td>S{{subject.id}}</td>
</tr>
</tbody>
</table>
Also, working fiddle here: http://jsfiddle.net/donal/r51d5fw5/17/
An alternative version, using nested ng-repeat, can be implemented using a div to display the nested subject information:
<tr ng-repeat="user in users">
<td>{{user.id}}</td>
<td>
<div ng-repeat="subject in user.subjects">S{{subject.id}}</div>
</td>
</tr>
rowspan will do everything you need. Follow this link:
w3schools This is one of the best resources for web development.
Using div u can also do
<div ng-repeat = "user in users">
<div> {{user.id}} </div>
<div ng-repeat = "user1 in users.subjects">
{{user1.id}} : {{user1.name}}
<div>
</div>
Donal's answer is good.
But I edited to show beautiful table:
<table class="table table-bordered table-hover table-height m-b-xs">
<thead>
<tr>
<td>ID</td>
<td>Subjects</td>
<td>name</td>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="user in users">
<td rowspan="{{user.subjects.length}}">key {{user.id}}</td>
<td>S{{ user.subjects[0].id }}</td>
<td>{{ user.subjects[0].name }}</td>
</tr>
<tr ng-repeat-end ng-repeat="subject in user.subjects.slice(1)">
<td>S{{subject.id}}</td>
<td>{{subject.name}}</td>
</tr>
</tbody>

nested arrays with ng-repeat and table html

I want to take this json place it into a HTML table.
"columns" : [
{
"id" : 0,
"column_name" : "Column 1",
"cards" : [
{
"id" : 0,
"task" : "Task 1"
},
{
"id" : 1,
"task" : "Task 2"
}
]
},
{
"id" : 1,
"column_name" : "Column 2",
"cards" : [
{
"id" : 0,
"task" : "Task 3"
}
]
}]
I have done quite a bit of searching on SO and cannot find why it is not doing what I expect.
https://jsfiddle.net/6nh100ca/9/
This is what I am expecting.
**Column 1 | Column 2**
Task 1 | Task 3
Task 2 |
https://stackoverflow.com/a/20063394/3279550
http://www.bennadel.com/blog/2456-grouping-nested-ngrepeat-lists-in-angularjs.htm
https://stackoverflow.com/a/26607425/3279550
This is what I have
<table >
<thead >
<tr>
<th ng-repeat="column in entity.columns">{{column.column_name}}</th>
</tr>
</thead>
<tbody ng-repeat="column in entity.columns" >
<tr ng-repeat="card in column.cards">
<td >{{card.task}}</td>
</tr>
</tbody>
</table>
If you want to stick with creating your own <table> manually, you need to pre-process your data object in order to fit the row logic. Try something like this fiddle:
Add this in your controller:
$scope.rowColumns = [];
$scope.columns.forEach(function(column, columnIndex){
column.cards.forEach(function (card, rowIndex){
if (!$scope.rowColumns[rowIndex])
$scope.rowColumns[rowIndex] = [];
$scope.rowColumns[rowIndex][columnIndex] = card;
});
});
console.log($scope.rowColumns);
Then add this in your html:
<tr ng-repeat="row in rowColumns">
<td ng-repeat="cell in row">
{{cell.task}}
</td>
</tr>
column.columnName should be column.column_name as per your example data, there after you could have two ng-repeat over a data where you will be actually have 1st ng-repeat over tbody & then the another will appear on tr. I'd prefer this approach when I have small data set. For larger data set the answer given by #Tiago is fine.
<table >
<thead >
<tr>
<th ng-repeat="column in entity.columns">{{column.columnName}}</th>
</tr>
</thead>
<tbody ng-repeat="column in entity.columns" >
<tr ng-repeat="card in column.cards">
<td >{{card.task}}</td>
</tr>
</tbody>
</table>

Categories

Resources