Multi-line table rows using angular - html

I am using angular.js to make a table like this:
<table>
<tr ng-repeat="order in orders">
<td>
{{order.custName}} ...(several columns)
</td>
</tr>
</table>
I would like to add a 2nd row for each order, so the table looks something like this:
order1ID order1Name order1Amnt
order1Comment
order2ID order2Name order2Amnt
order2Comment
order3ID order3Name order3Amnt
order3Comment
but I don't know how!

I have created a working CodePen example of how to solve this.
Relevant HTML:
<section ng-app="app" ng-controller="MainCtrl">
<table class="table table-bordered">
<thead>
<tr>
<th>Order ID</th>
<th>Order Name</th>
<th>Order Amount</th>
</tr>
</thead>
<tbody ng-repeat="order in orders">
<tr>
<td>{{order.id}}</td>
<td>{{order.name}}</td>
<td>{{order.amount}}</td>
</tr>
<tr>
<td colspan="3">
{{order.comment}}
</td>
</tr>
</tbody>
</table>
</section>
Relevant javascript:
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
$scope.orders = [{
id: '001',
name: 'Order 1 Name',
amount: 100.00,
comment: 'Order 1 comment goes here'
},{
id: '002',
name: 'Order 2 Name',
amount: 150.00,
comment: 'Order 2 comment goes here'
}];
});

Using Angular 1.2:
<table>
<tr ng-repeat-start="x in stuff">
<td>{{x.name}}</td>
</tr>
<tr ng-repeat-end="">
<td>{{x.value}}</td>
</tr>
</table>

Related

How to display object of array data on html table in Angular

I need to display below object of array in html table like that image. My data array like this.
data = [{id: 0 , name: 'one' , tags: ['a' , 'b' , 'c']} , {id: 1 , name: 'two', tags: ['r' , 't' , 'y']} , {id: 2 , name: 'three' , tags: ['a' , 'b' , 'c']} , {id: 3 , name: 'four' , tags: ['a' , 'b' , 'c']}]; .
So i tried like this but it's not working as expect on image.
<table class="table table-hover table-bordered">
<thead>
<tr>
<th scope="col">Tag Type</th>
<th scope="col">Tags</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let tag of data; let i = index">
<td>{{ tag.id }}</td>
<table class="table">
<tr *ngFor="let el of tag.tags">
<td>{{el}}</td>
</tr>
</table>
<td>
<div align="center">
<a matTooltip="edit tag"><i>mode_edit</i></a>
</div>
</td>
</tr>
</tbody>
</table>
this is the result i got.Any idea how to do this?
I have made a few modifications into the code.
Instead of creating a new nested table,I have tried create separate rows in the main table. I have hid the TagType And Action, where it is not to be displayed based on the index.
For the striped pattern, I have added "table-striped" class to the table.
The Html code would look like this
<table class="table table-hover table-bordered table-striped">
<thead>
<tr>
<th scope="col">Tag Type</th>
<th scope="col">Tags</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let tag of data; let i = index">
<tr *ngFor="let el of tag.tags; let i2=index">
<td *ngIf="i2==0"> {{tag.id}} </td>
<td *ngIf="i2!=0"> </td>
<td> {{el}} </td>
<td>
<div align="center">
<a matTooltip="edit tag"><i>mode_edit</i></a>
</div>
</td>
</tr>
</ng-container>
</tbody>
</table>
StackBlitz working demo: https://stackblitz.com/edit/angular-ivy-aqmrzy

How to iterate through an array of objects in angular

I have an array booksArr of objects of class book.
book.ts class
export class Book{
bookId:number;
bookName:string;
cost:number;
quantity:number;
constructor(bookId, bookType, cost, quantity){
this.cost=cost;
this.bookId=bookId;
this.bookName=bookName;
this.quantity=quantity;
}}
booksArr in books-list.component.ts
booksArr: book[] = [
new book(100, "The Alchemist", 20, 1),
new book(101, "Rich Dad Poor Dad", 50, 2),
new book(102, "Charolett's Web", 10, 1),
new book(103, "Harry Potter", 70, 4),
new book(104, "Gone Girl", 150, 3),
];
I want to create a table in html to display the details of these books.
books-list.component.html
<table border="1" *ngIf="bName">
<thead>
<tr>
<th>book ID</th>
<th>book Name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let b of booksArr">
<td *ngIf="b.//WHAT SHOULD I PUT HERE"</td>
</tr>
</tbody>
</table>
You are already iterating through the booksArr.just need to use interpolation to display the data. Try like this
<table border="1" *ngIf="bName">
<thead>
<tr>
<th>book ID</th>
<th>book Name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let b of booksArr">
<td>{{b.bookId}}</td>
<td>{{b.bookName}}</td>
</tr>
</tbody>
</table>
You are already iterating the array of books with *ngFor="let b of booksArr".
You want to now interpolate the values from each book in the array. When you are inside the array, you have access to the loop variable you declare in *ngFor. In this case the loop variable is b. You can now bind to the properties on b using curly brace interpolation. {{b.bookId}}.
<table border="1" *ngIf="bName">
<thead>
<tr>
<th>book ID</th>
<th>book Name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let b of booksArr">
<td>{{b.bookId}}</td>
<td>{{b.bookName}}</td>
</tr>
</tbody>
</table>
Try:
<td> {{ b.bookId }} </td>
<td> {{ b.bookName }} </td>
No *ngIf is required in this case. Just try the following
<tbody>
<tr *ngFor="let b of booksArr">
<td>{{b.bookId}}</td>
<td>{{b.bookName}}</td>
</tr>
</tbody>
And in your .ts file you should either change
constructor(bookId, bookName, cost, quantity)
Or
this.bookName=bookType;
inside your constructor

VueJS: V-for not displaying as desired

How can I get v-for to display table data in the same form as the following html:
<tr>
<th scope="col">Name</th>
<th scope="col">Price</th>
<th scope="col">Product ID</th>
<th></th>
</tr>
Currently I am using the following vue v-for code(below) but it is adding the table header(th) one below another. I would like the table header to display side by side.
<tr v-for="(column, index) in schema" :key="index">
<th scope="col">{{column}}</th>
</tr>
You just need to place v-for on the element you want to repeat, not it's parent.
For loop should be put on <th></th>
<tr>
<th v-for="(column, index) in schema" :key="index">{{column}}</th>
</tr>
Here is the official vue doc for list rendering: https://v2.vuejs.org/v2/guide/list.html
bind grid header and data separately.
<template>
<table>
<thead>
<tr>
<th v-for="(header,index) in gridHeader" :key="index">
{{header.displayName}}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(data, index) in gridData" :key="index" >
<td>
{{data.name}}
</td>
<td>{{data.age}}
</td>
<td>{{data.place}}
</td>
</tr>
</tbody>
</table>
</template>
<script lang="ts">
import Vue from 'vue';
export default class HelloWorld extends Vue {
private gridHeader: object[] = [
{name: 'Name', displayName: 'Name'},
{name: 'Age', displayName: 'Age'},
{name: 'Place', displayName: 'Place'}
];
private gridData: any =[{name:'Tony',age:'31',place:'India'},
{name:'Linju',age:'26',place:'India'},
{name:'Nysa',age:'12',place:'India'}];
};
</script>
<style scoped>
</style>

Unable to display NO DATA message when data does not exist in the table

I am displaying table data using NgTableParams in angularjs. I was trying to show NO DATA EXISTS in the table when the data is not available or length is zero, but my code doesn't seems to work.
Demo : http://plnkr.co/edit/nEbjQE1NQW7VF8dlZvyy?p=preview
sample code:
<table ng-table="tableParams" class="table" show-filter="true">
<tbody ng-repeat="user in $data">
<tr ng-show="$data.length > 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
{{user.name}}</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'">
{{user.age}}</td>
</tr>
<tr ng-show="$data.length === 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
NO DATA FOUND</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'">
</td>
</tr>
</tbody>
js code:
app.controller('MainCtrl', function($scope, NgTableParams) {
$scope.data1 = [];
console.log(" $scope.data1 length " + $scope.data1.length);
$scope.tableParams = new NgTableParams({}, { dataset: $scope.data1});
});
Tried as below too , but it is not displaying the table header and filter for the columns..
Demo : http://plnkr.co/edit/XAOO5tPALVOkQW9hhJCs?p=preview:
<tbody ng-show="!$data.length">
<tr>
<td>
NO DATA FOUND
</td>
</tr>
</tbody>
<tbody ng-repeat="user in $data">
<tr ng-show="$data.length > 0">
....
</tbody>
There are two issues here
The first one is that your ng-repeat directive is in your tbody this will cause your table body to be rendered for every single element in your array.
The second one is that your "NO DATA FOUND" message is inside of your ng-repeat block, no element will be rendered if $data is empty.
The solution would be to move the ng-repeat from your tbody to the actual element that you want to repeat for every item in your array, in this case, the tr that contains the data to be displayed.
<table ng-table="tableParams" class="table" show-filter="true">
<tbody>
<tr ng-repeat="user in $data" ng-show="$data.length > 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
{{user.name}}</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'">
{{user.age}}</td>
</tr>
<tr ng-show="$data.length === 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
NO DATA FOUND</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'"></td>
</tr>
</tbody>
</table>
Hope it helps!

Knockout foreach with nested tables

I have a bit of a unique situation, I am hoping knockout js provides a way to accomplish this.
I have the following structure:
Order = function() {
var self = this;
self.Name = 'default';
}
Customer = function() {
var self = this;
self.Name = 'default';
self.Orders = [];
}
I have the following table
<table>
<thead>
<tr>
<th>Customer Name</th>
</tr>
</thead>
<tbody data-bind="foreach: CustomerArray">
<tr>
<td data-bind="text: Name"></td>
</tr>
</tbody>
</table>
So this is great, it gives me a list of all my customer names.
Now for step two, I MUST format the table in a way that it lists. Order Name, then Customer Name at the bottom:
Customer Name (TH LABEL)
Order1
Order2
Order3
Smith, Frank
I came up with the idea of nesting my order array by including a tbody inside of each customer iteration, but I don't like this approach since the column width's from order to customer won't align since they are different tables.
Does anyone have any good ways to solve my unusual problem?
Thank you!
You could use "containerless control flow syntax" (Note 4 on the foreach docs) to render a TD for each order, then the customer, without a containing element:
<table>
<thead>
<tr>
<th>Customer Name</th>
</tr>
</thead>
<tbody data-bind="foreach: CustomerArray">
<!-- ko foreach: Orders -->
<tr>
<td data-bind="text: OrderDetails"></td>
</tr>
<!-- /ko -->
<tr>
<td data-bind="text: Name"></td>
</tr>
</tbody>
</table>
The commented block creates a binding scope just like the one on TBODY, but without the containing element.
This should work :
<table>
<thead>
<tr>
<th>Customer Name</th>
</tr>
</thead>
<tbody data-bind="foreach: CustomerArray">
<!-- ko foreach: Orders -->
<tr>
<td data-bind="text: Name"></td>
</tr>
<!-- /ko -->
<tr>
<td data-bind="text: Name"></td>
</tr>
</tbody>
</table>
I hope it helps.