Here is the stackblitz code.
As you can see
-
First lets see what projection/ngContent is.
Projection is a very important concept in Angular. It enables developers to build reusable components and make applications more scalable and flexible.
In more simple words it helps in adding content dynamically which can come from server as html or text inside the component without creating DOM node like document.createtextnode().
Refrence for projection: https://angular-2-training-book.rangle.io/handout/components/projection.html
Projection is similar to angularjs transclusion in directives.
https://docs.angularjs.org/api/ng/directive/ngTransclude
Lets jump to your problem.
That's right we need two loops for repeating content in Odd and even numbers acc. to your requirement. reason: ngFor adds new instance of same template in DOM.
Working code
https://stackblitz.com/edit/angular-ymznfu?file=app%2Fapp.component.html
Example:
App.component.html
<child>
<ng-container odd>//this will work
<ul>{{number[1]}}</ul>
</ng-container>
</child>
child.component.html
<ng-content select="[odd]"></ng-content>
Above example will work reason, We are projecting outermost dom node in ngContent.
You can try projecting below code
app.component.html
<child>
<ng-container>
<ng-content select="[odd]"></ng-content>
</ng-container>
</child>
above code will not project reason Angular checks only the outermost node available in the component i.e the reason in your code
<ul odd>Something</ul>
is projecting and others not.
讨论(0)
-
You can do it this way with two loops:
<div>
<ng-container *ngFor="let number of numbers; let isFirst=first">
<h2 *ngIf="isFirst">Odd Numbers</h2>
<p>{{(number%2>0? number : '')}}</p>
</ng-container>
<ng-container *ngFor="let number of numbers; let isFirst=first">
<h2 *ngIf="isFirst">Even</h2>
<p>{{(number%2==0? number : '')}}</p>
</ng-container>
</div>
讨论(0)
-
You cannot do this, without two loops. The reason being ng-content
is a placeholder, which accepts dynamic html inside. Now when you loop inside your code, you don't assign anything to the even
or odd
selector. But if you change your code to below
<child>
<div *ngFor="let number of numbers;let i = index" even>
<div *ngIf="(number%2 !== 0);else even">
<ul>{{number}}</ul>
</div>
<ng-template #even>
<ul>{{number}}</ul>
</ng-template>
<!-- <ul even>Why its rendering and not others??</ul> -->
</div>
</child>
You will see the output change to
This is because no the output of ng-For
has been assigned to the even
selector.
If you change the template to below
<child>
<div *ngFor="let number of numbers;let i = index" odd>
<div *ngIf="(number%2 !== 0)">
<ul>{{number}}</ul>
</div>
</div>
<div *ngFor="let number of numbers;let i = index" even>
<div *ngIf="(number%2 == 0)">
<ul>{{number}}</ul>
</div>
</div>
</child>
It will work
Also remember inside a ng-For
you cannot append content to a even
or odd
section, even if that feature was available it would have overwritten the section with the last value.
Leaving even ng-for
out of it. The below code
<child>
<div>
<div odd>
This should be under odd
</div>
</div>
</child>
Also won't work
So what you are trying to achieve and the way you are trying to achieve it is not supported by angular.
讨论(0)
-
One of the solutions is to sort your numbers array. You can use your own pipe:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'oddFirst'})
export class OddFirstPipe implements PipeTransform {
transform(numbers: number[], args: any[]): number[] {
const odd = numbers.filter(num => num % 2 !== 0);
const even = numbers.filter(num => num % 2 === 0);
return [...odd, ...even];
}
}
Then you can use it in your template:
<div *ngFor="let number of numbers | oddFirst">
<div *ngIf="(number%2 !== 0);else even">
<ul odd>{{number}}</ul>
</div>
<ng-template #even>
<ul even>{{number}}</ul>
</ng-template>
</div>
讨论(0)
-
You can do it with pure CSS.
Take a look at the modified StackBlitz.
https://stackblitz.com/edit/angular-zto8w1?file=app/app.component.html
CSS display grid works wonders. Keep in mind it's not (fully) supported on IE.
讨论(0)
-
It's because of nesting.
I ran some experiments on stackblitz and it seems that the contents cannot be nested at all and we just cannot blame the *ngFor
for it. Even using ng-container
on the for loop did not help.
讨论(0)