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

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>

Related

Reorder Table columns Angular 8

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>

Vue <router-link> not clickable

I'm trying to set up a Vue app with some simple routing so I can navigate to different pages. I installed Vue-Router through npm and I've tried following a couple tutorials online but, I can't seem to figure out why my is not clickable or why, when I manually type in the URL, it doesn't change anything. Any help is appreciated. Thank you.
main.js:
import {createApp} from 'vue'
import App from './App.vue'
import "./vue-api-call/styles.css"
import VueRouter from 'vue-router'
import About from "./About"
import Home from "./Home";
const routes = [
{path: '/about', component: About},
{path: '/home', component: Home}
]
const router = new VueRouter({routes})
createApp(App, router).mount("#app")
export default router
App.vue:
<!-- This first part of the file, the template part, is basically like an HTML page. Whatever we put in here will
display when we use 'npm run serve'. -->
<template>
<!-- The <div> tag is used as a container for HTML elements - which is then styled with CSS or manipulated with
JavaScript. -->
<div id="app">
<!-- <nav>Hello</nav>-->
<!-- The router-view tag will display info that comes from the router-link tag. More information here:
https://next.router.vuejs.org/guide/#html -->
<router-view>
<router-link to="/about">About</router-link>
</router-view>
<Layout>
<!-- begin form -->
Add a new video game with the form below:
<form id="demo">
<!-- text -->
<br>
<p>
<input type="text" v-model="msg" placeholder="Add Game">
{{ msg }}
</p>
<br>
<p>
<input type="checkbox" v-model="checked">
{{ checked ? "yes" : "no" }}
</p>
<br>
<!-- select -->
<p>
<select v-model="selected">
<option>one</option>
<option>two</option>
</select>
</p>
<br>
<p>
<button type="submit" v-on:click="createVideoGame()">Submit Form</button>
</p>
</form>
<br>
<button v-on:click="customer()"> Customer Button</button>
<br>
<table>
<thead>
<tr>
<th scope="col">Customer ID</th>
<th scope="col">First Name</th>
<th scope="col">Last Name</th>
<th scope="col">Middle Name</th>
<th scope="col">Birthday</th>
<th scope="col">Gender</th>
<th scope="col">Email</th>
<th scope="col">Username</th>
<th scope="col">Is Deleted</th>
</tr>
</thead>
<tbody>
<tr v-for="customer in customerInfo" :key="customer.customerId">
<td>{{ customer.customerId }}</td>
<td>{{ customer.cusFirstName }}</td>
<td>{{ customer.cusLastName }}</td>
<td>{{ customer.cusMiddleName }}</td>
<td>{{ customer.dateOfBirth }}</td>
<td>{{ customer.gender }}</td>
<td>{{ customer.email }}</td>
<td>{{ customer.username }}</td>
<td>{{ customer.isDeleted }}</td>
</tr>
</tbody>
</table>
<br><br>
<button v-on:click="videoGame()"> VideoGame Button</button>
<br>
<table>
<thead>
<tr>
<th scope="col">Video Game ID</th>
<th scope="col">Title</th>
<th scope="col">Release Year</th>
<th scope="col">Price</th>
<th scope="col">Stock</th>
<th scope="col">Image</th>
</tr>
</thead>
<tbody>
<tr v-for="game in gameInfo" :key="game.videoGameId">
<td>{{ game.videoGameId }}</td>
<td>{{ game.videoGameTitle }}</td>
<td>{{ game.yearReleased }}</td>
<td>{{ game.price }}</td>
<td>{{ game.stock }}</td>
<td>{{ game.videoGameImage }}</td>
</tr>
</tbody>
</table>
<br><br>
<button v-on:click="order()"> Order Button</button>
<br>
<table>
<thead>
<tr>
<th scope="col">Order ID</th>
<th scope="col">Order Date</th>
<th scope="col">Credit Card Provider</th>
<th scope="col">Credit Card Number</th>
<th scope="col">Total</th>
<th scope="col">Subtotal</th>
<th scope="col">Discount</th>
<th scope="col">Customer ID</th>
<th scope="col">Address ID</th>
</tr>
</thead>
<tbody>
<tr v-for="order in orderInfo" :key="order.orderId">
<td>{{ order.orderId }}</td>
<td>{{ order.orderDate }}</td>
<td>{{ order.creditCardProvider }}</td>
<td>{{ order.creditCardNumber }}</td>
<td>{{ order.total }}</td>
<td>{{ order.subtotal }}</td>
<td>{{ order.discount }}</td>
<td>{{ order.customerId }}</td>
<td>{{ order.addressId }}</td>
</tr>
</tbody>
</table>
<br><br>
<button v-on:click="purchase()"> Purchase Button</button>
<br>
<table>
<thead>
<tr>
<th scope="col">Purchase ID</th>
<th scope="col">Order ID</th>
<th scope="col">Video Game ID</th>
<th scope="col">Shipment Date</th>
</tr>
</thead>
<tbody>
<tr v-for="[purchase] in [purchaseInfo]" :key="purchase.purchaseId">
<td>{{ purchase.purchaseId }}</td>
<td>{{ purchase.orderId }}</td>
<td>{{ purchase.videoGameId }}</td>
<td>{{ purchase.shipmentDate }}</td>
</tr>
</tbody>
</table>
<br><br>
<button v-on:click="address()"> Address Button</button>
<br>
<table>
<thead>
<tr>
<th scope="col">Address ID</th>
<th scope="col">Customer ID</th>
<th scope="col">State ID</th>
<th scope="col">City</th>
<th scope="col">Zip</th>
<th scope="col">Suite Number</th>
<th scope="col">PO Box</th>
</tr>
</thead>
<tbody>
<tr v-for="address in addressInfo" :key="address.addressId">
<td>{{ address.addressId }}</td>
<td>{{ address.customerId }}</td>
<td>{{ address.stateId }}</td>
<td>{{ address.city }}</td>
<td>{{ address.zip }}</td>
<td>{{ address.suiteNumber }}</td>
<td>{{ address.poBox }}</td>
</tr>
</tbody>
</table>
<br><br>
<button v-on:click="state()"> State Button</button>
<br>
<table>
<thead>
<tr>
<th scope="col">State ID</th>
<th scope="col">State</th>
</tr>
</thead>
<tbody>
<tr v-for="state in stateInfo" :key="state.stateId">
<td>{{ state.stateId }}</td>
<td>{{ state.state }}</td>
</tr>
</tbody>
</table>
<br><br>
</Layout>
</div>
</template>
<!-- Still not entirely sure what this script part is. Pretty sure it's some functionality stuff added by Vue -->
<script>
import Layout from "./components/Layout.vue"
import axios from "axios"
// import PageHeading from "./components/PageHeading.vue"
// import NavBar from "./components/NavBar.vue"
export default {
name: 'App', variant: "variant", variantType: "variantType", disableButton: "disableButton",
username: "", password: "",
data: () => {
return {
// These variables are used above and are what initially is shown above the buttons.
customerInfo: [],
gameInfo: [],
orderInfo: "waiting for order",
purchaseInfo: "waiting for purchase",
addressInfo: "waiting for address",
stateInfo: "waiting for state",
username: "",
password: "",
msg: "",
checked: true,
picked: "",
selected: ""
}
},
components: {
Layout,
// NavBar, PageHeading,
},
mounted() {
// this.test()
},
methods: {
// Gets customer info and displays it.
customer: function () {
if (this.customerInfo === "waiting for customer") {
axios
.get('http://localhost:8000/customers/?format=json')
.then(response => (this.customerInfo = response.data))
} else {
this.customerInfo = "waiting for customer"
}
},
// Gets video game info and displays it.
videoGame: function () {
if (this.gameInfo === "waiting for game") {
axios
.get('http://localhost:8000/videoGames/?format=json')
.then(response => (this.gameInfo = response.data))
} else {
this.gameInfo = "waiting for game"
}
},
// Gets order info and displays it.
order: function () {
if (this.orderInfo === "waiting for order") {
axios
.get('http://localhost:8000/orders/?format=json')
.then(response => (this.orderInfo = response.data))
} else {
this.orderInfo = "waiting for order"
}
},
// Gets purchase info and displays it.
purchase: function () {
if (this.purchaseInfo === "waiting for purchase") {
axios
.get('http://localhost:8000/purchases/?format=json')
.then(response => (this.purchaseInfo = response.data))
} else {
this.purchaseInfo = "waiting for purchase"
}
},
// Gets address info and displays it.
address: function () {
if (this.addressInfo === "waiting for address") {
axios
.get('http://localhost:8000/addresses/?format=json')
.then(response => (this.addressInfo = response.data))
} else {
this.addressInfo = "waiting for address"
}
},
// Gets state info and displays it.
state: function () {
if (this.stateInfo === "waiting for state") {
axios
.get('http://localhost:8000/states/?format=json')
.then(response => (this.stateInfo = response.data))
} else {
this.stateInfo = "waiting for state"
}
},
createVideoGame() {
axios.post('http://127.0.0.1:8000/videoGames/', {
videoGameId: '111',
videoGameTitle: 'Test Video Game 1',
yearReleased: '2021',
price: '10.00',
stock: '5',
videoGameImage: 'testImage'
})
},
// login: function () {
// console.log(this.username)
// console.log(this.password)
// const bcrypt = require("bcryptjs")
// bcrypt.compare(this.password, "hash", (err, result) => {
// if (err) {
// console.error(err)
// return
// }
// console.log(result) // true or false
// });
}
}
// methods: {
// addUser(){
// console.log(this.encryptPassword(this.password))
// },
// encryptPassword(password)
// const salt = bcrypt.genSaltSync(10)
// return bcrypt.hashSync(password, salt)
// },
</script>
<!-- This style tag is for the entire page, I think. If you change something in here, like the background-color, it
will change it on the webpage. It's exactly like the style tag in a CSS/HTML page I'm pretty sure. -->
<!-- if you use the !important; rule, it will override ALL previous styling rules for that specific property on that
element! -->
<style>
body {
margin: 0;
padding: 0;
background-color: #c5fcc5 !important;
}
table, th, td {
border: 1px solid darkgreen;
text-align: center;
}
</style>
You forgot to tell Vue to use the VueRouter. From the Official Docs.
import { createApp } from 'vue';
import App from './App.vue';
...
...
const routes = [
{path: '/about', component: About},
{path: '/home', component: Home}
];
const router = new VueRouter({routes});
createApp(App).use(router).mount('#app'); // <== Here
export default router;

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")

Table inside table using ng-repeat in angularjs

I am new to angularjs and web-development .I am using ng-repeat to represent the data in a complicated table , like this :
A B C D
abc pqr xyz std
So,This is the code :
<div class="table-responsive">
<table class="table table-striped table-bordered report-table table-fixed" contextmenu-container="meta.contextmenu" fixed-header>
<thead class="text-center text-info">
<th class="text-center">A</th>
<th class="text-center">B</th>
<th class="text-center">C</th>
<th class="text-center">D</th>
</thead>
<tr ng-repeat="report in reports.data">
<td class="text-center">{{ report.attributes.annotation }}</td>
<td class="td-report-field" contenteditable="{{enableReportEditing}}" contextmenu-item="report" context-menu="menuOptions">{{ report.attributes.field }}</td>
<td>
<input type="checkbox" ng-if="report.attributes.message && showcheckbox" ng-bind="report.attributes.message" ng-click="getcheckedData(report.attributes.message)">
<span ng-if="report.attributes.message" contentEditable ng-model="report.attributes.message">
{{ report.attributes.message }}
</span>
<span ng-if="!report.attributes.message">{{ report.attributes.message }}</span>
</td>
<td class="text-center">{{ report.attributes.score }}</td>
</tr>
</table>
</div>
And the json is like :
{
"type": "report",
"id": 14,
"attributes": {
"annotation": "abc",
"field": "pqr",
"message": "xyz",
"score": "7"
},
"innerAnnotations": {
{
"annotation": "jkl",
"field": "pqr",
"message": "xyz",
"score": "6"
},
{
"annotation": "Qualification",
"field": "EFG",
"message": "HIJ",
"score": "5"
}
}
},
Now table should look like -(abc will be the parent)
A B C D
abc pqr xyz 7
jkl pqr xyz 6
Qualification EFg Hij 5
So, I have tried some things but no luck. Can any one please help me to solve this ? Any help will be great.
You have mentioned wrong data in ng-repeat
ng-repeat="report in reports.data"
Replace it with
ng-repeat="report in reports.innerAnnotations". Also you need to change the inner html angular expressions too.

How do I iterate over an array within an object within an array using *ngFor in angular 2?

Background:
I have an array called game that consists of seven objects that represent each round in the game. Within each object I have details about that round such as 'roundNumber', 'title', 'players', and 'winner'. The 'players' property is an array of 'player' objects which contains the score for that player on that particular round.
game = [
{
roundNumber: 1,
title: "2 Books",
players: [
{
pk: 1,
username: "James",
score: 5,
},
{
pk: 2,
username: "Jim",
score: 54,
},
{
pk: 3,
username: "Bob",
score: 22,
},
],
winner: undefined,
},
{
roundNumber: 2,
title: "1 Book 1 Run",
players: [
{
pk: 1,
username: "James",
score: 54,
},
{
pk: 2,
username: "Jim",
score: 32,
},
{
pk: 3,
username: "Bob",
score: 76,
},
],
winner: undefined,
},
//etc
//etc
//etc
];
What I want to happen:
I want to be able to loop through all of this data and place it in a table on my template using *ngFor.
<table id="data-table" class="table table-striped">
<thead>
<tr>
<th *ngFor="let round of game">{{ round.title }}</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let player of round of game"> //HOW DO I STRUCTURE MY LOOP HERE?
<td>{{ }}</td>
<td>{{ }}</td>
<td>{{ }}</td>
<td>{{ }}</td>
<td>{{ }}</td>
<td>{{ }}</td>
<td>{{ }}</td>
</tr>
</tbody>
</table>
As you can see, I've looped though the top level array but I don't know how to loop through each player on each round. Any help would be greatly appreciated. It should look something like this:
Loop though each rounds in TR and td for each player.
<tr *ngFor="let round of game">
<td *ngFor="let player of round.players">{{ player.score }}</td>
</tr>
note your rounds and players data should be in same manner for each array good luck.
You can use the extended syntax of *ngFor here:
<table id="data-table" class="table table-striped">
<ng-template ngFor let-round [ngForOf]="game">
<thead>
<tr>
<th>{{ round.title }}</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let player of round.players">
<td>{{ }}</td>
<td>{{ }}</td>
<td>{{ }}</td>
<td>{{ }}</td>
<td>{{ }}</td>
<td>{{ }}</td>
<td>{{ }}</td>
</tr>
</tbody>
</ng-template>
</table>

Categories

Resources