Nested ngFor using outer index in inner loop - html

Given a list of elements:
const l = ["one", "two", "three", "four", "five", "six", "seven"]
We want to create 1 row for every 3 elements in the list, and (up to) 3 columns per row.
In this case, the resulting html would look like:
<div class="row">
<div class="col"><p>one</p></div>
<div class="col"><p>two</p></div>
<div class="col"><p>three</p></div>
</div>
<div class="row">
<div class="col"><p>four</p></div>
<div class="col"><p>five</p></div>
<div class="col"><p>six</p></div>
</div>
<div class="row">
<div class="col"><p>seven</p></div>
</div>
How can I dynamically do this? The only way I can see to accomplish this is a nested ngFor loop, but there doesn't seem to be a way to use the outer index value in the inner for loop. How can one do this?
Something like:
<div *ngFor="let content of l; index as i">
<div class="row" *ngIf="i % 3 === 0">
<div class="col" *ngFor="<!--HOW TO ACCOMPLISH THIS FOR LOOP? j = i; j < i + 3; j++ -->">
<p [innerHTML]="l[j]"></p>
</div>
</div>
</div>

You can do it like this:
<ng-container *ngFor="let content of [].constructor(l.length); let item_index = index">
<div class="row" *ngIf="item_index % 3 === 0">
<ng-container *ngFor="let item of [0, 1, 2]; let column_index = index">
<ng-container *ngIf="item+item_index < l.length">
<div class="col">
<p [innerHTML]="l[item + item_index]"></p>
</div>
</ng-container>
</ng-container>
</div>
</ng-container>
Working example

Related

How do I display ngFor data outside of ngFor loop angular?

I have two ngFor loops in my component.
<ng-container *ngFor="let x of xs; let i = index">
<ng-template #printData>
<p>
<span>Test</span>
</p>
</ng-template>
<p>
<span>{{x}}</span>
</p>
<!-- Iterate ys-->
<ng-container *ngFor="let y of ys[i]; let j = index">
<ng-container *ngIf="j==0 && y?.value; else normalPrintData">
<ng-container *ngTemplateOutlet="printData"></ng-container>
</ng-container>
<ng-template #normalPrintData>
<p *ngIf="y?.value">
<span>Test</span>
</p>
</ng-template>
</ng-container>
basically I have two for loops but I want to display printData above the normal "x" interpolation if some condition is satisfied. I tried using ngTemplateOutlet but that does not work because the template is just printed at the ng-container that its called from.
Using an ngIf works but I feel a better solution can be achieved. Please help.
How about using ng-template context and setting the x property.
<ng-container *ngFor="let x of xs; let i = index">
<ng-template #printData>
<p>
<span>{{x}}</span>
</p>
<p>
<span>Test</span>
</p>
</ng-template>
<!-- Iterate ys-->
<ng-container *ngFor="let y of ys[i]; let j = index">
<ng-container *ngIf="j==0 && y?.value; else normalPrintData">
<ng-container *ngTemplateOutlet="printData; context: {x}"></ng-container> <!-- <------ changed here -->
</ng-container>
<ng-template #normalPrintData>
<p *ngIf="y?.value">
<span>Test</span>
</p>
</ng-template>
</ng-container>

*ngFor to print only the first element of an array

i'm using this code:
<div *ngIf="gamedata.notOver" class="columns">
<div class="column has-text-centered" *ngFor="let board of boards; let i = index">
<table class="is-bordered" [style.opacity]="i == player ? 0.5 : 1">
<tr *ngFor="let row of board.tiles; let j = index">
<td *ngFor="let col of row; let k = index" (click)="boardListener($event)" [style.background-color]="col.used ? '' : 'transparent'" [class.win]="col.status == 'win'" [class.fail]="col.status !== 'win'" class="battleship-tile" id="t{{i}}{{j}}{{k}}">
{{ col.value == "1" ? (col.status == "hit" ? "💀" : "X") : (col.status == "miss" ? "⛶" : (col.status == "hit" ? "💀" : "🌊")) }}
</td>
</tr>
</table>
<hr>
</div>
</div>
to print the first element of an array of arrays that contains 2 elements, how can i choose to print the first or the second element without printing both of them? i need to do this since i have to put both of them in separate divs.
I assume the line that refers to the array of arrays is the board of boards one.
Try wrapping each array in an ng-content that has an ngIf directive as follows:
<div class="column has-text-centered" *ngFor="let board of boards; let i = index">
<ng-content *ngIf="i%2 == 0">
INSERT WHAT YOU WANT TO DISPLAY FOR FIRST ARRAY ITEM HERE
</ng-content>
<ng-content *ngIf="i%2 != 0">
INSERT WHAT YOU WANT TO DISPLAY FOR SECOND ARRAY ITEM HERE
</ng-content>
</div>
You may have to repeat some code, but it should work.

How to print a table from a 2D Array in Angular 5?

I'm trying to print a table from a 2 dimensional array of objects, holding a attribute 'text'. It only prints the table rows, iterating through the fields doesn't work.
My component.html looks like this:
<section *ngIf="object">
<table>
<tr *ngFor="let row of array; let even = even; let odd = odd"
[ngClass]="{ odd: odd, even: even }">
<td class="field" *ngFor="let field of array[row]">
{{field.text}}
</td>
</tr>
</table>
</section>
The array: object[][] is filled correctly and i can log the 'text' attributes to the console. The Problem is: I don't know how to iterate through the 2nd dimension (*ngFor="let field of array[row]")
Assuming array is an array of arrays,
Your second ngFor should be *ngFor="let field of row"
You can't use array[row] since row contains the array of the second dimension and not the index.
<section *ngIf="object">
<table>
<tr *ngFor="let row of array; let even = even; let odd = odd"
[ngClass]="{ odd: odd, even: even }">
<td class="field" *ngFor="let field of row">
{{field.text}}
</td>
</tr>
</table>
</section>
Example

how to display only selected columns and ignore empty cells in html table using ngFor

I am trying to display specific columns in table in angular 2. So my table element looks like this:
<table class="ui single line table" id="tablej">
<tbody>
<tr *ngFor="let row of data;let i=index">
<td *ngFor="let val of row;let j=index" >
<div *ngIf="j<=2 || j==9 || j==17||j==20||j==21">
{{val}}
</div>
</td>
</tr>
</tbody>
</table>
I am getting empty spaces for skipped columns and my table became uneven. Is there any way to display specific columns and ignore the rest?
You can wrap your tr within a template tag to display or not display that column:
<template *ngFor="let row of data;let i=index">
<tr *ngIf="condition to display this column">
<td *ngFor="let val of row;let j=index" >
<div *ngIf="j<=2 || j==9 || j==17||j==20||j==21">
{{val}}
</div>
</td>
</tr>
</template>
The conditional row might be:
<template *ngFor="let row of data;let i=index">
<tr *ngIf="displayRow(row)">
<td *ngFor="let val of row;let j=index" >
{{val}}
</td>
</tr>
</template>
public displayRow(row):boolean {
return row.length <= 2 || row.length == 9 || row.length == 17 || row.length == 20 || row.length == 21
}
Hope that helps

Suppress display of Table fields in HTML / ASP.NET

I inherited a web app built in ASP.NET which returns a table of query results which pull from a database. Right now, all fields display as text, with the exception of the "Url" column which is a hyperlink (as seen in below code). What code would I add if I wanted to also suppress the display of one of the columns returned (or just not return it at all if that makes more sense)?
EDIT - additional information: the table columns are not pre-defined anywhere in the source code. The app has the ability for you to define a database and table from which to pull the results of your query - therefore the resulting table is dynamic. This is why it seems it has to be done in the HTML code of the page itself.
Below is the HTML code for the table:
<div class="row" ng-if="loading || results != null">
<div class="col-lg-2" ng-show="facets">
<div class="widget">
<div class="widget-title">
<i class="fa fa-check-square-o"></i> Facets
</div>
<div class="widget-body xlarge no-padding">
<pre>{{ facets | json }}</pre>
</div>
</div>
</div>
<div ng-class="{ 'col-lg-10': facets != null, 'col-lg-12': facets == null }">
<div class="widget">
<div class="widget-title">
<i class="fa fa-bars"></i> Results <span>({{ count }} results)</span>
</div>
<div class="widget-body xlarge no-padding">
<div class="message" ng-if="!loading && (results == null || results.length == 0)">
<div class="alert alert-warning">The query did not return any results.</div>
</div>
<div class="table-responsive" ng-if="!loading && results != null && results.length > 0">
<table class="table table-hover">
<thead>
<tr>
<th ng-repeat="field in fields">
{{field}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="result in results">
<td ng-repeat="field in fields">
<div ng-if="field == 'Url'">
{{ result.DirectSourceUrl }}
</div>
<div ng-if="field !== 'Url'">
{{ result[field] }}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
I am not a .NET expert but i do know angular so if i get your question right, just ignore the field you wanna delete and don't bind it in the html or you could do something like this in angular controller right after the results are returned response.data.fieldName=undefined; (fieldName is the name off the column you wanna delete.
Hope it helped you.