I am new in angular and I am using ngFor inside a to populate a table. My question is, if the array that is present[let i of user.acessTypes] in ngFor is empty how can I show an "Is Empty" string information in the correspondent row?
This is my table html
<table class="table table-bordered">
<tr>
<th>Email</th>
<th>Acess Type</th>
</tr>
<tr *ngFor="let user of listUser">
<td>{{user.email}}</td>
<td>
<button class="btn btn-primary"
*ngFor="let i of user.acessTypes">
//if i is empty show "Is Empty"
{{i.accessTypeName}}({{i.subAcessTypeName}})
</button> </td>
</tr>
</table>
This is my JSON response
{
"data": [
{
"id": 1,
"email": "jose#hotmail.com",
"password": "$2a$10$44ghfG4Ym4COxXbj9pDBuOLBXCPRRDiIM7y77G.XEh7avm2GOxlUC",
"isAdmin": 0,
"acessTypes": [
{
"id": 1,
"accessTypeName": "User",
"subAcessTypeName": "Ver&Escrever"
}
],
"tomas": [],
"consultas": [],
"profile": "NORMALUSER"
}
],
"dataArray": null,
"errors": []
}
There are several approaches. One of them is working with an if-else statement the Angular way. Both ng-container and ng-template won't be part of the DOM tree after they are rendered.
Here is a nice resource that explains it in more detail: https://toddmotto.com/angular-ngif-else-then
<table class="table table-bordered">
<tr>
<th>Email</th>
<th>Acess Type</th>
</tr>
<tr *ngFor="let user of listUser">
<td>{{user.email}}</td>
<td>
<ng-container *ngIf="user.acessTypes.length > 0; else noAccessTypes">
<button class="btn btn-primary" *ngFor="let i of user.acessTypes">
{{i.accessTypeName}}({{i.subAcessTypeName}})
</button>
</ng-container>
<ng-template #noAccessTypes>
<button class="btn btn-primary">Is empty</button>
</ng-template>
</td>
</tr>
</table>
<table class="table table-bordered">
<tr>
<th>Email</th>
<th>Acess Type</th>
</tr>
<tr *ngFor="let user of listUser">
<td>{{user.email}}</td>
<td>
<button class="btn btn-primary"
*ngFor="let i of user.accessTypes">
//if i is empty show "Is Empty"
{{i.accessTypeName}}({{i.subAcessTypeName}})
</button>
<button class="btn btn-primary" *ngIf="user.accessTypes.length == 0">Is Empty</button>
</td>
</tr>
</table>
You can just check using *ngIf as follows,
<button class="btn btn-primary" *ngFor="let i of user.acessTypes">
<ng-template *ngIf="i">
{{i.accessTypeName}}({{i.subAcessTypeName}})
</ng-template>
<ng-template *ngIf="!i">
Is Empty
</ng-template>
</button> </td>
Simply you can create a proper validation check as follows.
<table class="table table-bordered">
<tr>
<th>Email</th>
<th>Acess Type</th>
</tr>
<tr *ngFor="let user of listUser">
<td>{{user.email}}</td>
<td>
<button class="btn btn-primary"
*ngFor="let i of user.acessTypes">
<div *ngIf="i.accessTypeName.length == 0">
Is Empty
</div>
<div *ngIf="i.accessTypeName.length != 0">
{{i.accessTypeName}}({{i.subAcessTypeName}})
</div>
</button>
</td>
</tr>
</table>
Related
The html is printing all the API data in the table. Products and Components
The table should not print the product when the components are empty. What is the best way to do this?
I'm using angular 8
products = {
"id": 1,
"name": "John",
"components": [
{
"id": 130,
"name": "Price",
}
]
"isSelected": false }
products = {
"id": 2,
"name": "name",
"components": [] }
<div class="card">
<div class="card-body">
<table class="table table-striped table-bordered hover">
<thead>
<tr>
<th width="1%" class="text-center"></th>
<th width="8%" class="text-center">Id</th>
<th width="8%" class="text-center">Name</th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let product of products; index as i">
<tr>
<td>
<div>
<button class="btn btn-sm btn-default"></button>
</div>
</td>
<td>{{product.id}}</td>
<td>{{product.name}}</td>
</tr>
<tr *ngFor="let prodComp of product.components">
<td></td>
<td>{{prodComp.id}}</td>
<td>{{prodComp.name}}</td>
</tr>
</ng-container>
</tbody>
</table>
</div>
</div>
You could add another container inside your *ngFor using *ngIf to test for that condition:
<ng-container *ngFor="let product of products; index as i">
<ng-container *ngIf="product.components.length > 0">
<tr>
<td>
<div>
<button class="btn btn-sm btn-default"></button>
</div>
</td>
<td>{{product.id}}</td>
<td>{{product.name}}</td>
</tr>
<tr *ngFor="let prodComp of product.components">
<td></td>
<td>{{prodComp.id}}</td>
<td>{{prodComp.name}}</td>
</tr>
</ng-container>
</ng-container>
So here's my html code:
<div class="container">
<div>
<h1 class="table-title">Employees</h1>
<table class="table">
<thead class="thead-dark">
<tr>
<th>User Name</th>
<th>Email</th>
<th>Role</th>
<th>References</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let tempEmployee of employees">
<td class="align-middle">{{ tempEmployee.userName }}</td>
<td class="align-middle">{{ tempEmployee.email }}</td>
<td class="align-middle">{{ tempEmployee.roleId }}</td>
<td class="align-middle">
<a routerLink="/projects">Assigned Projects</a>
<br />
Assigned Tickets
</td>
</tr>
</tbody>
</table>
</div>
<div>
<h4>Select 1 or multiple users</h4>
<select id="user-list" multiple size="employees.length" >
<option
*ngFor="let employee of employees; let indexOfEmployee=index;"
value="indexOfEmployee"
>{{ employee.userName }}</option>
</select>
<button id="submit" type='submit' class="btn btn-primary" (click)="onSubmit()">Submit</button>
</div>
</div>
I'm confused on how I can know if an option is selected so that in the component on the onSubmit() function i can check if an option is selected and submit it. Also multiple options can be selected.
I tried to console.dir the option element to see if it has a selected property but maybe i'm missing something.
some quick and easy javascript:
for(var i = 0; i < document.getElementById("user-id").length; i++){
if(document.getElementsByTagName("option")[i].selected == true){
console.log("selected")
}
}
This is my HTML code for my table to display list of users:
<table class="table m-table m-table--head-bg-metal">
<thead>
<tr>
<th>
Nom
</th>
<th>
Prénom
</th>
<th>
Email
</th>
<th>
Action
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Jhon
</td>
<td>
Stone
</td>
<td>
jhonStone#gmail.com
</td>
<td>
<button class="btn btn-outline-danger m-btn m-btn--icon btn-sm m-btn--icon-only m-btn--pill m-btn--air" (click)="onDisableUser()">
<i class="fa fa-close"></i>
</button>
</td>
</tr>
</tbody>
This is typescript method:
onDisableUser(){
//this is the method to disable the table row..
}
What I want is when I click () on the action button, the table row will be disabled.
Thanks in advance.
What do you mean with disable?
If you want to remove the list item do this on the html :
<table class="table m-table m-table--head-bg-metal">
<thead>
<tr>
<th>
Nom
</th>
<th>
Prénom
</th>
<th>
Email
</th>
<th>
Action
</th>
</tr>
</thead>
<tbody>
<tr *ngIf="!isDisable">
<td>
Jhon
</td>
<td>
Stone
</td>
<td>
jhonStone#gmail.com
</td>
<td>
<button class="btn btn-outline-danger m-btn m-btn--icon btn-sm m-btn--icon-only m-btn--pill m-btn--air" (click)="onDisableUser()">
<i class="fa fa-close"></i>
</button>
</td>
</tr>
</tbody>
</table>
And on the typescript:
isDisable = false;
onDisableUser(){
this.isDisable = true;
}
If you want to disable it with css use this in html:
<tr [ngClass]="{'disabled': isDisable}>
You can use the css method to disable the table row.
Set the disabled to true when clicked and set the class to the <tr> if disabled=true
.disable{
cursor: not-allowed;
}
<table>
<tr class="disable">
<td> akjsd </td>
</tr>
<tr >
<td> akjsd </td>
</tr>
</table>
isDisable = false;
onDisableUser(){
this.isDisable = true;
}
I'm attempting to return two tr elements from a single component v-design-row. I know vue requires the template elements to be wrapped in a div, but I cannot wrap them in a div because of the tag structure html tables require. When I add the second tr in the v-design-row component then vue doesn't render anything.
Can anyone suggest the best method for accomplishing this?
main.vue
<table class="table">
<thead>
<th>Image</th>
<th>Name</th>
<th>Description</th>
<th>Status</th>
<th>Order</th>
<th>Edit</th>
<th>Delete</th>
</thead>
<tbody v-for="catagory in catagories">
<v-catagory-row :catagory="catagory"></v-catagory-row>
<v-design-row v-for="design in catagory.designs" :design="design"></v-design-row>
</tbody>
</table>
v-design-row.vue
<template>
<tr>
<td><img :src="design.image_directory" :alt="design.name"></td>
<td>{{ design.name }}</td>
<td>
<button class="btn btn-secondary" type="button" data-toggle="collapse" :data-target="'#' + design.identifier" aria-expanded="false" :aria-controls="design.identifier">
<i class="fa fa-plus" aria-hidden="true"></i> Show
</button>
</td>
<td>
<div class="switch">
<input :id="'active'+design.id" v-model="design.active" class="btn-toggle btn-toggle-round-flat" type="checkbox">
<label :for="'active'+design.id"></label>
</div>
</td>
<td>
<button class="btn btn-secondary" type="button">
<i class="fa fa-caret-up" aria-hidden="true"></i>
</button>
<button class="btn btn-secondary" type="button">
<i class="fa fa-caret-down" aria-hidden="true"></i>
</button>
{{ design.sort_order }}
</td>
<td>
<button class="btn btn-secondary" type="button">
<i class="fa fa-pencil" aria-hidden="true"></i>
</button>
</td>
<td>
<button class="btn btn-secondary" type="button">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</td>
</tr>
<tr>
<td class="p-0" colspan="7">
<div class="collapse" :id="design.identifier">
<div class="p-3">
{{ design.description }}
</div>
</div>
</td>
</tr>
</template>
You are allowed to group row using multiple <tbody> sections like this:
<table>
<thead>
<tr> ... </tr>
</thead>
<tbody>
<tr> ... </tr>
<tr> ... </tr>
</tbody>
<tbody>
<tr> ... </tr>
<tr> ... </tr>
</tbody>
</table>
You can use this in templates by using a <tbody> as the root element:
<template>
<tbody>
<tr> ... </tr>
<tr> ... </tr>
</tbody>
</template>
Since second tr in your v-design-row contains description of design, I'd suggest that this is whole element and it should occupy one row and have its own layout.
Alternatively, you can have a description separately and all other data in component.
Also, statement
vue requires the template elements to be wrapped in a div
is not quite correct. Template can have any root element while it is a single element. So you can have
<template>
<tr>
</tr>
</template>
or even
<template>
<tr v-if="condition == 1">
</tr>
<tr v-else-if="condition == 2">
</tr>
<tr v-else>
</tr>
</template>
You can use vue-fragment library. It allows you to have wrapper that wont actually be rendered.
https://www.npmjs.com/package/vue-fragment
I am trying to make table in which there are two show/hide buttons for two columns say A and B.. button a and b separately are functioning properly but If i use both in table ... only one of them functions properly other doesn't do anything.. pls hlp me i am new to this
<table datatable="ng" class="row-border hover table table-condensed no-margin">
<thead>
<tr>
<th>#</th>
<th>Username</th>>
<th>Profile</th>
<th>Points</th>
<th>Forcasts Won/Lost</th>
<th>Invites</th>
<th>Referrals</th>
<th>Activity</th>
<th>Most Used Redeemption Gateway</th>
<th>Most Read FAQ</th>
<th>Promo Codes used</th>
<th>Suspend/Unsuspend</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="person in showCase.persons">
<td>{{person.id}}</td>
<td>{{person.uname}}</td>
<td>
<button type="button" class="btn btn-primary" ng-if="person.Profexpanded" ng-click="person.Profexpanded = false;person.Invexpanded=false">Hide</button>
<button type="button" class="btn btn-primary" ng-if="!person.Profexpanded" ng-click="person.Profexpanded = true;person.Invexpanded=false">Show</button>
</td>
<td>{{person.points}}</td>
<td>{{person.forcasts}}</td>
<td style="padding:5px">
<table><tbody>
<tr><td><b>sent: </b></td> <td>{{person.invites[0].sent}}</td></tr>
<tr><td><b>accepted:</b></td> <td>{{person.invites[0].accepted}}</td></tr>
</tbody></table>
</td>
<td>{{person.referrals}}</td>
<td>
<button type="button" class="btn btn-primary" ng-if="person.Invexpanded" ng-click="person.Invexpanded = false;person.Profexpanded = false">Hide</button>
<button type="button" class="btn btn-primary" ng-if="!person.Invexpanded" ng-click="person.Invexpanded = true;person.Profexpanded = false">Show</button>
</td>
<td>{{person.muredempt}}</td>
<td>{{person.mfaq}}</td>
<td>{{person.promocodes}}</td>
<td>{{person.isSuspended}}</td>
</tr>
<tr ng-if="person.Profexpanded" ng-repeat-end="">
<td class = "profile" colspan="5">
Hello A
</td>
</tr>
<tr ng-if="person.Invexpanded" ng-repeat-end="">
<td>Hello B</td>
</tr>
</tbody>
</table>
<!--end .card-body -->
</div>`
Maybe try ng-show instead ng-if <tr ng-show="person.Invexpanded" ng-repeat-end="">
Use
<tr ng-if="person.Profexpanded">
instead of
<tr ng-if="person.Profexpanded" ng-repeat-end="">