HTML Table automatically starts splitting rows into new columns - html

My problem is that HTML table instead of displaying Rows vertically, after some rows it starts to put them into a new column automatically, in this order:
|Row1 | Row3 | Row4 |
|Row2 |
But I only need it to go vertically just in one column:
|Row1|
|Row2|
|Row3|...
Below my table's HTML code and how I am loading in data:
<table id="coinflip-table">
<tbody id="coinflip-list">
<tr>
#if (ViewBag.CoinflipAll != null)
{
foreach (CoinFlip.Main.Models.CoinflipViewModel cfGames in Model.Coinflips)
{
<td>
<img class="coinflip-list-avatar" src="#cfGames.User1_IconUrl" />
#if (cfGames.Status != 0)
{
<span class="coinflip-vs-player">VS</span>
<img class="coinflip-list-avatar" src="#cfGames.User2_IconUrl" />
}
</td>
<td class="coinflip-list-skins">
#if (ViewBag.WeaponBet != null)
{
foreach (CoinFlip.Main.Models.WeaponWebViewModel wep in ViewBag.WeaponBet)
{
<img class="coinflip-list-skins-small" title="#wep.Name" src="#wep.ImageUrl">
}
}
</td>
<td>
<span class="coinflip-value">$#cfGames.TotalValue</span>
</td>
<td></td>
<td>
<button class="coinflip-list-action" type="button" data-toggle="modal">WATCH</button>
</td>
}
}
</tr>
</tbody>
</table>
And I cannot seem to understand the cause of it. Is there a solution to this, just to go vertically? In JS, CSS or HTML? Or the issue can be related somewhere else?
Any help is appreciated,
Cheers

you need to include <tr> tag in loop to get row foreach list
or
if you need vertical row within a column try this!
<!-- Row -->
<tr>
<!-- Column -->
<td>
<!-- Row Within Column -->
<tr>
<td></td>
</tr>
</td>
</tr>
comment below if you have any questions?

If you need your table to be built vertically you have to put your foreach loop around < tr > < /tr > elements

Related

How to find if parent row has child rows in a html table

I have the following incomplete code :
if (tr.attr('data-depth') == 0 && **tr.children()** {
}
The double star marked above is incomplete.
In the above code, what i want to achieve is check for a parent row( that i am doing by checking tr.attr('data-depth')==0) and then check if that parent row has any child rows and if no child rows are present for that parent row ,then remove a custom class which i am doing between the curly braces.
How to achieve the same?
Any code sample would be very helpful.
You can check the parent row has any row as child with find('tr') and check anything has been found with .length
This code is an example. You can modify it according to your needs.
$('tr[data-depth = 0]').each(function(){
if( $(this).find('tr').length > 0)
$(this).css('background-color','red')
})
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr data-depth = 0>
<td>
<table>
<tr>
<td>
1
</td>
</tr>
<tr>
<td>
2
</td>
</tr>
</table>
</td>
</tr>
<tr data-depth = 0 >
<td>
3
</td>
</tr>
<tr>
<td>
4
</td>
</tr>
</table>
For easier expression you must select your exact tr element
let my_row = // Your target row
if( $(my_row).data('depth') == 0 && $(my_row).find('tr').length > 0)
{
// Do something
}

Table and row span

I have a source of data from a service like the following.
this.ateco2007 = [{code: this.anagrafica?.ateco2007?.code, description: this.anagrafica?.ateco2007?.description}]
if(this.anagrafica?.atecoSecondari && this.anagrafica?.atecoSecondari.length > 0) {
let i = 0;
for(let elem of this.anagrafica.atecoSecondari) {
this.atecoSecondari.push({
index: i++,
code: elem.code,
description: elem.description
});
}
...where ateco2007 has got always one elem, instead atecoSecondari can have multiple values. But there is always a pair code/description.
I want to show this data in a table. The first row will always be one row(ateco 2007), the other rows can be multiple.
I want a structure like this:
The first column will be always fix with the label, the second column shows the code and the last the description.
I tried the following, this is almost correct:
But I want to achieve something closer to the following:
As you see, there is a sort of rowspan and in the second and third columns, the rows have borders and are in the same line.
I tried the following code:
<p-table [value]="ateco2007" [autoLayout]="true">
<ng-template pTemplate="body">
<tr>
<td class="font-weight-bold"> {{'cliente.ateco'|translate}}</td>
<td>{{ateco2007[0]?.code}}</td>
<td class="text-left">{{ateco2007[0]?.description}}</td>
</tr>
<tr>
<td rowspan="atecoSecondari.length" class="font-weight-bold">
{{'cliente.atecoSecondari'|translate}}</td>
<td>
<table>
<tr *ngFor="let elem of atecoSecondari">
<td>{{elem.code}}</td>
</tr>
</table>
</td>
<td>
<table>
<tr *ngFor="let elem of atecoSecondari">
<td class="text-left">{{elem.description}}</td>
</tr>
</table>
</td>
</tr>
</ng-template>
But I don't know if it's the best way to build the table.
I solved it in this way
<p-table [value]="ateco2007" [autoLayout]="true">
<ng-template pTemplate="body" let-rowIndex="rowIndex">
<tr>
<td class="font-weight-bold"> {{'cliente.ateco'|translate}}</td>
<td>{{ateco2007[0]?.code}}</td>
<td class="text-left">{{ateco2007[0]?.description}}</td>
</tr>
<tr *ngFor="let elem of atecoSecondari">
<td *ngIf="rowIndex == elem.index" [attr.rowspan]="atecoSecondari.length" class="font-weight-bold">
{{'cliente.atecoSecondari'|translate}}
</td>
<td>{{elem.code}}</td>
<td class="text-left">{{elem.description}}</td>
</tr>
</ng-template>
</p-table>
I added the rowspan and changed the structure.

Non Repeating Table Footer That Avoids Breaking Over Printed Pages CSS

So I have a weird situation were I have a table footer that I only need to repeat once so I decided to just add the "footer" trs to the end of the tbody so it would only appear once at the end of the table and look like a footer without the repeating on each printed page.
<table>
<tbody>
#foreach(var item in Model.Items)
{
<tr><td>#item.Name</td></tr>
<tr><td>#item.Total</td></tr>
}
<tr>
<td>Total</td>
<td>#Model.Items.Sum(x => x.Total)</td>
</tr>
<tr>
<td>Discount</td>
<td>#(Model.Items.Sum(x => x.Total) / 50)</td>
</tr>
</tbody>
</table>
This was fine until Model.Items had enough rows that it pushed the second row of the footer onto the next page when I need to keep the two footer rows together.
I've also tried using the actual tfoot tag like so with a page-break-inside:avoid style.
<table>
<tbody>
#foreach (var item in Model.Items)
{
<tr><td>#item.Name</td></tr>
<tr><td>#item.Total</td></tr>
}
</tbody>
<tfoot style="page-break-inside:avoid;">
<tr>
<td>Total</td>
<td>#Model.Items.Sum(x => x.Total)</td>
</tr>
<tr>
<td>Discount</td>
<td>#(Model.Items.Sum(x => x.Total) / 50)</td>
</tr>
</tfoot>
</table>
This kept the footer together but its now repeating on each page instead of once. Someone on another Stack Overflow question suggested using the following style on the tfoot to stop it repeating which worked, but now it ignores the page-break-inside:avoid style.
<tfoot style="display: table-row-group"></tfoot>
Does anyone know how to get a footer to appear once and avoid breaking over multiple printed pages?
I got it working but I had to apply a few styles to make it looks like one table. I put the original footer HTML into a tr > td > table like so:
<table>
<tbody>
#foreach (var item in Model.Items)
{
<tr><td>#item.Name</td></tr>
<tr><td>#item.Total</td></tr>
}
<tr style="page-break-inside:avoid;">
<td colspan="2">
<table>
<tr>
<td>Total</td>
<td>#Model.Items.Sum(x => x.Total)</td>
</tr>
<tr>
<td>Discount</td>
<td>#(Model.Items.Sum(x => x.Total) / 50)</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
This allowed the footer to stay together while only appearing once at the end of the page.

HtmlAgilityPack reading table after specified table

I have similiar structure to this:
<table class="superclass">
<tr>
<td>
</td>
<td>
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
</tr>
</table>
<table cellspacing="0">
<tr>
<td>
</td>
<td>
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
</tr>
</table>
This is how I get the first table with class:
HtmlNode firstTable = document.DocumentNode.SelectSingleNode("//table[#class=\"superclass\"]");
Then I read the data. However I don't know how to get straight to the another table and read that data too. Any ideas?
I'd rather avoid counting which table it is and then using index to that table.
There is XPath following-sibling axis which allows you to get element following current context element at the same level :
HtmlNode firstTable = document.DocumentNode.SelectSingleNode("//table[#class=\"superclass\"]");
HtmlNode nextTable = firstTable.SelectSingleNode("following-sibling::table");
If you want to access multiple nodes, you can consider SelectNodes(xpath) method over SelectSingleNode(xpath) method.
I'll provide a sample code here for reference, it may not work towards your need.
var tables = htmlDocument.DocumentNode.SelectNodes("//table");
foreach (HtmlNode table in tables)
{
if (table.GetAttributeValue("class", "").Contains("superclass"))
{
//this is the table of class="superclass"
}
else
{
//this is the other table.
}
}

Adding data into rows of next column

Basically I am creating a data grid that displays data from different tables in database.I am using ASP.NET MVC4 for this.
Following is how my part of my code looks:
<table class="myTable">
<tbody>
#foreach (var item in Model.sets)
{
<tr class="parent" data-level="0">
<td>
#item.setName
#* Here my logic would go*#
</td>
</tr>
}
So after displaying the rows of name of sets,in the next column I would want to display the elements that belong to that set.So I wrote another for loop in <td></td> that would loop through the Model.elements and check if it belongs to that set and display it.But I am getting "Element td cannot be nested within element td " validation error.
So how can I add data into rows of the next column?
Put your logic below the first end td tags instead. You can't put td tags inside other td tags; a series of sibling td tags make up a row.
If you want each separate piece of data in its own column:
#foreach (var item in Model.sets)
{
<tr class="parent" data-level="0">
<td>
#item.setName
</td>
#foreach (var element in Model.elements)
{
<td>
#*logic here*#
</td>
}
</tr>
If you want all your content inside the same cell, then you want:
#foreach (var item in Model.sets)
{
<tr class="parent" data-level="0">
<td>
#item.setName
</td>
<td>
#foreach (var element in Model.elements)
{
#*logic here*#
}
</td>
</tr>
}