Angular CDK table: Element 'td' cannot be nested inside element 'table' - html

I'm trying to use the Angular CDK table in an Angular 7 project in Visual Studio 2017. When I follow the official code sample from here it works perfectly but I get these warnings from visual studio: Element 'td'/'th' cannot be nested inside element 'table'.
Below is the code for reference:
<table cdk-table [dataSource]="masterIds">
<ng-container cdkColumnDef="name">
<th cdk-header-cell *cdkHeaderCellDef> Name </th>
<td cdk-cell *cdkCellDef="let id"> {{ ws[id].Name }} </td>
</ng-container>
<ng-container cdkColumnDef="code">
<th cdk-header-cell *cdkHeaderCellDef> Code </th>
<td cdk-cell *cdkCellDef="let id"> {{ ws[id].Code }} </td>
</ng-container>
<tr class="small" cdk-header-row *cdkHeaderRowDef="['name', 'code']"></tr>
<tr cdk-row *cdkRowDef="let id; columns: ['name', 'code']" [routerLink]="['./', id]"></tr>
</table>
Any idea how to get rid of these warnings? They are poking me in the eye. Thanks
UPDATE
Here is a picture of the warnings:
And the green squiggles :

I just found a way which "seems" to work; wrap all the column definitions inside an invisible <tr> element and that's that:
<table cdk-table [dataSource]="masterIds">
<tr style="display:none!important">
<ng-container cdkColumnDef="name">
<th cdk-header-cell *cdkHeaderCellDef> Name </th>
<td cdk-cell *cdkCellDef="let id"> {{ ws[id].Name }} </td>
</ng-container>
<ng-container cdkColumnDef="code">
<th cdk-header-cell *cdkHeaderCellDef> Code </th>
<td cdk-cell *cdkCellDef="let id"> {{ ws[id].Code }} </td>
</ng-container>
</tr>
<tr class="small" cdk-header-row *cdkHeaderRowDef="['name', 'code']"></tr>
<tr cdk-row *cdkRowDef="let id; columns: ['name', 'code']" [routerLink]="['./', id]"></tr>
</table>

A th should be inside a tr, you should have something like :
<table>
<tr>
<th></th>
<th></th>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</table>
For your updated question
That's because of the Visual studio compiler itself, you can search for How to suppress VS studio compiler warnings (try this), and a tip: switch to VsCode for your frontend dev.

Related

ERROR Error: dataKey must be defined to use row expansion

I'm trying to figure out how to use Row Expansion in PrimeEng. I was just following the guide in their documentation and it shows that I should define my datakey. I already defined it below if I'm not mistaken. I'm new to this, please don't judge.
<p-table [value]="users" [paginator]="true" [rows]="10" [showCurrentPageReport]="true"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
[rowsPerPageOptions]="[10, 25, 50]">
<ng-template pTemplate="header">
<tr>
<th style="width:2rem">blank</th>
<th style="width:1rem">ID</th>
<th style="width:8rem">Name</th>
<th style="width:8rem">Username</th>
<th style="width:8rem">Email</th>
<th style="width:8rem">Street</th>
<th style="width:8rem">Suite</th>
<th style="width:8rem">City</th>
<th style="width:8rem">Zip code</th>
<th style="width:8rem">LAT</th>
<th style="width:8rem">LNG</th>
<th style="width:8rem">Phone</th>
<th style="width:8rem">Website</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-user let-expanded="expanded">
<tr>
<td>
<!-- <button type="button" pButton pRipple (click)="viewPostUser(user.id)" class="p-button-text p-button-rounded p-button-plain" ></button> -->
<button type="button" pButton pRipple [pRowToggler]="posts" (click)="viewPostUser(user.id)" class="p-button-text p-button-rounded p-button-plain" [icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></button>
</td>
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.username}}</td>
<td>{{user.email}}</td>
<td>{{user.address.street}}</td>
<td>{{user.address.suite}}</td>
<td>{{user.address.city}}</td>
<td>{{user.address.zipcode}}</td>
<td>{{user.address.geo.lat}}</td>
<td>{{user.address.geo.lng}}</td>
<td>{{user.phone}}</td>
<td>{{user.website}}</td>
</tr>
</ng-template>
Here is my row expansion ng-template.
<ng-template pTemplate="rowexpansion" let-posts>
<tr>
<td colspan="7">
<div class="p-p-3">
<p-table [value]="posts.userId" [dataKey]="posts.userId">
<ng-template pTemplate="header">
<tr>
<th style="width:4rem">userID</th>
<th style="width:4rem">ID</th>
<th style="width:4rem">Title</th>
<th style="width:4rem">Body</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-posts>
<tr>
<td>{{posts.userId}}</td>
<td>{{posts.id}}</td>
<td>{{posts.title}}</td>
<td>{{posts.body}}</td>
<td><p-button type="button" icon="pi pi-search"></p-button></td>
</tr>
</ng-template>
</p-table>
</div>
</td>
</tr>
</ng-template>
I've tried searching the error that I have, but it points me to updating the version.
I think here is where you get it wrong:
[value]="posts.userId" [dataKey]="posts.userId"
[value] is the collection that you want to iterate through, which should be posts in this case
[dataKey] is the property of one item in that collection which you could just define by name: userId
So the final code is:
[value]="posts" [dataKey]="userId"
First, to fix the error you're seeing, add the attribute dataKey="id" to the p-table element.
Next, using let-posts is probably not what you wanted. You didn't write how your data structure is constructed but I'll assume each user has a property called posts. You need to change your template like this:
<ng-template pTemplate="rowexpansion" let-user>
<tr>
<td colspan="7">
<div class="p-p-3">
<p-table [value]="user.posts" dataKey="id">
<ng-template pTemplate="header">
<tr>
<th style="width:4rem">userID</th>
<th style="width:4rem">ID</th>
<th style="width:4rem">Title</th>
<th style="width:4rem">Body</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-post>
<tr>
<td>{{post.userId}}</td>
<td>{{post.id}}</td>
<td>{{post.title}}</td>
<td>{{post.body}}</td>
<td><p-button type="button" icon="pi pi-search"></p-button></td>
</tr>
</ng-template>
</p-table>
</div>
</td>
</tr>
</ng-template>
Explanation:
Use let-user in the rowexpansion template. Now the user variable will contain the user data for the current expandable row.
In the inner p-table, provide the [value] input with the data for the sub table, i.e., the posts for the current user.
In the inner p-table, provide the dataKey input with the name of the field which is the unique key of the table. This might be even not necessary in your case.
In the inner p-table, in the body template, use let-post instead of let-posts since each iteration, i.e., each row of the inner table showing posts for the user, will store the current row, which is a single post.
In each <td> element in the inner table's body template, use post.<field-name>. post will contain the data for the current row so all you need to do is access the field you need inside the object.
You can add dataKey in first line, like this
<p-table [value]="users" dataKey="name">
Maybe it will solve your problem.

Create Angular2 Table Header with *ngFor loop

So, my problem is so basic but i cant solve it.
I'm trying to create dynamic table header with *ngFor.
<table>
<tr>
<th>Entry Warehouse</th>
<th colspan="2" *ngFor="let data of datas">
SomeText
</th>
</tr>
<tr>
<th>More Text</th>
<div *ngFor="let data of datas">
<th>A little text again</th>
<th>A little text again</th>
</div>
</tr>
</table>
Anyway, this solution suicide themself at that point. If datas length more than 1, div tag is underscoring th tag in same cell.
If i try another solution like this;
<table>
<tr>
<th>Entry Warehouse</th>
<th colspan="2" *ngFor="let data of datas">
SomeText
</th>
</tr>
<tr>
<th>More Text</th>
<th *ngFor="let data of datas">A little text again</th>
<th *ngFor="let data of datas">A little text again</th>
</tr>
</table>
it looks like works but actually not. Because at this time the next th tag doesnt start before the previous loop ends.
In angular 2+ you can use<ng-container> tags
<ng-conatiner *ngFor="let i of items">
<th>i</th>
</ng-conatiner>

Uikit Progress bar on Uikit Table

I have problem putting a uikit progress bar inside a uikit table cell, i have searched for getuikit for progress bar and table documentation I googled everything but found no any good community or resources out there.
Here is my simplified html file for table:
<table class="uk-table uk-table-hover uk-overflow-container">
<thead>
<tr>
<th>
Employee
</th>
<th>
<label class="uk-form-label" for="name" style="font-weight: lighter;">
Contact
</label>
</th>
<th>
Workplace/Position
</th>
<th>
Status
</th>
<th>
Work Completed (%)
</th>
</thead>
<tbody>
<tr>
<td>Luigi Lascuña</td>
<td>Igi#skyes8.com</td>
<td>Main Office/General Manager</td>
<td>Regular</td>
<td class="uk-progress">
<div class="uk-progress-bar" style="width: 40%;">40%</div>
</td>
</tr>
</tbody>
</table>
Here is my output:
There result will only display the 40% text inside a table cell but
not just like in the documentation.
I just include the components/progress.css to my styles block in the head of the main html file. This solved my problem!

AngularDart ng-repeat in tables?

I'm trying to iterate over lists with sublists, and printing them as <tr> without much success.
This code illustrates what i want to accomplish:
<table>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
<span ng-repeat='x in [["a1","a2"],["b1","b2"],["c1","c2"]]'>
<tr>{{x.length}}<tr>
<span ng-repeat='y in x'>
<tr>{{y}}<tr>
</span>
</span>
</table>
I would expect this to show:
<table>
<tr>3</tr>
<tr>a1</tr>
<tr>a2</tr>
<tr>b1</tr>
// and so on..
</table>
what should i do to make this work? I want to be able to repeat without the need to put in spans..
Only table tags (td, th, tr, tbody...) inside of <table> tag are shown, you should add ng-repeat to <tr>
If you use angular1.2 or higher you can use ng-repeat-start and ng-repeat-end tags:
html:
<table ng-controller="apiCtrl">
<tr ng-repeat-start="item in foo" ng-init="first=item[0]">
<td>first: {{ first }}</td>
</tr>
<tr ng-repeat-end ng-init="last = item[1]">
<td>last: {{ last }}</td>
</tr>
</table>
js:
function apiCtrl($scope) {
$scope.foo = [
['one', 'uno'],
['two', 'dos'],
['three', 'tres']
];
}
Here is JSfiddle
Here is fiddle with nested lists
This question is really old and AngularDart has changed a lot in the meantime. We can use the <ng-container> tag to apply all kinds of directives to a group of tags which are to be repeated or put under an *ngIf and so forth. The <ng-container> tag will not appear in the DOM output, but its contents will be there and affected by the specified directive.
<table>
<ng-container *ngFor="let row of matrix">
<tr>
<ng-container *ngFor="let value of row">
<td>{{value}}</td>
</ng-container>
<tr>
</ng-container>
</table>
When your component.dart has:
List<List<int>> get matrix => [[1, 2, 3], [4, 5, 6]];

Using multiple ngrepeat in one html element / or workaround?

I want to make a table like below:
<table>
<thead>
<tr>
<th rowspan="2" ng-repeat="item in someitems">{{ item.title }}</th>
<th colspan="{{ group.items.length }}" ng-repeat="group in some_item_groups">{{ group.title }}</th>
</tr>
<tr>
<th ng-repeat="item in (group in some_item_groups).items">{{ item.title }}</th>
</tr>
</thead>
<tbody>
...
</tbody>
</table>
(I tried to add table pic here but don't have enough reputation points.)
Is there any way to draw this type of table with angular ng-repeat?