Angular access index outside *ngFor in angular - html

I have a list like this
<ul>
<li *ngFor="let product of items.Products| slice 0:3 ; let i = index">
{{ product?.ProductsDescription}}
<li>
</ul>
All i want i to is, display a list of products, but i wan't to limit the exibition to only 3 products, and below, in another <li></li> display "And more {{ quantity-left-of-products }}"
Example:
I Have 6 products, so it would display:
Item 1
Item 2
Item 3
And more 3
Something like this:
In my knowledge i would have to find a way to access the index property outside the ngFor.
Can anyone help me?

You can achieve what you want without accessing the index value outside the context.
Create a variable in TS to use it as a parameter in the slice pipe.
sliceValue = 3;
loadMore() {
this.sliceValue = items.Products.length;
}
Template:
<ul>
<li *ngFor="let product of items.Products| slice 0:sliceValue ; let i = index">
{{ product?.ProductsDescription}}
<li>
<li (click)="loadMore()" *ngIf="items.Products.length > sliceValue">And more {{items.Products.length - sliceValue}}</li>
</ul>
Use *ngIf for displaying the "And More" when necessary. When the user clicks on "And More" the <li> for "And More: hides and the rest of the list loads.

Related

Loop using *ngFor in angular from the last element to first element [duplicate]

Using Angular 2, I want to duplicate a line in a template multiple times. Iterating over an object is easy, *ngFor="let object of objects". However, I want to run a simple for loop, not a foreach loop. Something like (pseudo-code):
{for i = 0; i < 5; i++}
<li>Something</li>
{endfor}
How would I do this?
You could dynamically generate an array of however time you wanted to render <li>Something</li>, and then do ngFor over that collection. Also you could take use of index of current element too.
Markup
<ul>
<li *ngFor="let item of createRange(5); let currentElementIndex=index+1">
{{currentElementIndex}} Something
</li>
</ul>
Code
createRange(number){
// return new Array(number);
return new Array(number).fill(0)
.map((n, index) => index + 1);
}
Demo Here
Under the hood angular de-sugared this *ngFor syntax to ng-template version.
<ul>
<ng-template ngFor let-item [ngForOf]="createRange(5)" let-currentElementIndex="(index + 1)" [ngForTrackBy]="trackByFn">
{{currentElementIndex}} Something
</ng-template>
</ul>
You can instantiate an empty array with a given number of entries if you pass an int to the Array constructor and then iterate over it via ngFor.
In your component code :
export class ForLoop {
fakeArray = new Array(12);
}
In your template :
<ul>
<li *ngFor="let a of fakeArray; let index = index">Something {{ index }}</li>
</ul>
The index properties give you the iteration number.
Live version
Depending on the length of the wanted loop, maybe even a more "template-driven" solution:
<ul>
<li *ngFor="let index of [0,1,2,3,4,5]">
{{ index }}
</li>
</ul>
You can do both in one if you use index
<div *ngFor="let item of items; let myIndex = index>
{{myIndex}}
</div>
With this you can get the best of both worlds.
The better way to do this is creating a fake array in component:
In Component:
fakeArray = new Array(12);
InTemplate:
<ng-container *ngFor = "let n of fakeArray">
MyCONTENT
</ng-container>
Plunkr here
you can use _.range([optional] start, end). It creates a new Minified list containing an interval of numbers from start (inclusive) until the end (exclusive). Here I am using lodash.js ._range() method.
Example:
CODE
var dayOfMonth = _.range(1,32); // It creates a new list from 1 to 31.
//HTML Now, you can use it in For loop
<div *ngFor="let day of dayOfMonth">{{day}}</div>
The best answer for this question I have found here
You need to create an attribute inside your class and reference it to Array object:
export class SomeComponent {
Arr = Array; //Array type captured in a variable
num:number = 20;
}
And inside your HTML you can use:
<ul id="next-pages">
<li class="line" *ngFor="let _ of Arr(10)"> </li>
</ul>
queNumMin = 23;
queNumMax= 26;
result = 0;
for (let index = this.queNumMin; index <= this.queNumMax; index++) {
this.result = index
console.log( this.result);
}
Range min and max number
for Example let say you have an array called myArray if you want to iterate over it
<ul>
<li *ngFor="let array of myArray; let i = index">{{i}} {{array}}</li>
</ul>
If you want to use the object of ith term and input it to another component in each iteration then:
<table class="table table-striped table-hover">
<tr>
<th> Blogs </th>
</tr>
<tr *ngFor="let blogEl of blogs">
<app-blog-item [blog]="blogEl"> </app-blog-item>
</tr>
</table>
If you want duplicate lines multiple time.
You can simply do :-
declare in .ts file
public repeater = "<li>Something</li>";
Then use following to print it .html file.
{{repeater.repeat(5)}}

How I can get definite value in keyvalue pair?

My object has a specific set of key / value pairs,
i want to get a specific value, not everything, how can i do this?
For example:
.ts
movie = {
title:'title',
description:'descriprtion',
rating:4
};
html:
<ul *ngFor="let item of movie | keyvalue">
<li> {{item.value}} </li>
</ul>
And I only want to receive item.description, can you tell me how this can be implemented?
<ul *ngFor="let item of movie | keyvalue">
<ng-container *ngIf="item.key === 'description'">
<li>{{item.value}}</li>
</ng-container>
</ul>
But to be honest you would be better off just doing:
<div>{{ move.description }}</div>
Since you do not seem to want to iterate the object props, but only want description.

display multiple nested data with angular6

I'm receiving JSON data from an API which has some child objects as well. The API has a menu level and down the menu, it's having meals. What I want to do is to display meals relating to each menu under the menu
JSON from API
[{"id":6,"name":"Menu 1","serveDate":"2019-05-10","meals":[{"id":13,"name":"Rice with Stew","description":"rice","image":"","mealType":"BREAKFAST","unitPrice":5,"status":"ENABLED"}]},{"id":5,"name":"Menu 2","serveDate":"2019-06-10","meals":[{"id":13,"name":"Corn Flakes,"description":"Flakes","image":"","mealType":"BREAKFAST","unitPrice":5,"status":"ENABLED"}]},{"id":4,"name":"Menu 3","serveDate":"2019-07-10","meals":[]}]
HTML
<div *ngFor="let item of menuList">
<h2>Menu</h2>
{{item.name}} - {{item.servate}}
<h2 *ngFor="let item of menuList.meals">Meals</h2>
{{item.name}} - {{item.mealType}}
</div>
JS
getMenus() {
this.menuServices.menuList(this.pagedData)
.subscribe(
response => {
if (response && response.code === HttpStatus.OK) {
this.menuList = response.data;
}
},
);
}
Any help on how to make this work correctly the way it should work?
<div *ngFor="let menu of menuList">
<h2>Menu</h2>
{{menu.name}} - {{menu.servate}}
<h2>Meals</h2>
<ng-container *ngFor="let meal of menu.meals">
{{meal.name}} - {{meal.mealType}}
</ng-container>
</div>
Using this way you don't have to add unnecessary divs or any other html tag for looping in angular.
this is the perfect way to do nested loops without changing your html
No need to access the main list as you have your meals array in the item object.
Change HTML Code to:
<div *ngFor="let item of menuList">
<h2>Menu</h2>
{{item.name}} - {{item.servate}}
<h2>Meals</h2>
<div *ngFor="let item of item.meals">
{{item.name}} - {{item.mealType}}
</div>
</div>
When you're doing something like let item of menuList that means the item variable should be used to refer to an individual item within your loop. To avoid confusion, I'd also recommend naming these item vars for nested loops differently.
Another important thing to keep in mind that all the markup that you want to be output for each array item should be wrapped with an element with *ngFor. It's not the case with your <h2> tag being printed for each meal, but not the meal description.
Edit the template as follows:
<div *ngFor="let menuItem of menuList">
<h1>Menu</h1>
<h2>{{menuItem.name}} - {{menuItem.serveDate}}</h2>
<p>maybe description here</p>
<h3>Meals</h2>
<p *ngFor="let mealItem of menuItem.meals">{{mealItem.name}} - {{mealItem.mealType}}</p>
</div>

Angular updating array view Typescript

So I have an array that I need to display, problem is the array can't be populated until the page is already displayed and the user has entered a value
Stepping through my code I can see that the array is being populated correctly, however, the view isnt updated
I'm able to update it using this and an on click event
 
onAddClick(){ this.CarTypes.push(newAddCar("1",true,true,1,1,"1","1"))
}
But when I call it through a method, it doesn't update, even though the parameters are 100% correct
add(NMsg:string, Nom: boolean, show: boolean,image: number, order: number, id: string, name:string){
    this.CarTypes.push(newAddCar(NMsg,Nom,show,image,order,id,name))
  }
Can anyone help?
<div>
<!--<ul *ngFor="let cars of CarTypes" (click)="Click(cars)">
{{ cars.CarTypes.length ? cars.CarTypes[0].Name : '' }}
</ul>-->
<ul>
<li *ngFor="let cars of CarTypes" >
{{cars.Name}}
</li>
<button (click)="onAddClick()">Add</button>
</ul>
<!--<select name="selectedcar" [(ngModel)]="selectedcar" ng-repeat="car as car.Name in CarTypes">{{cars}}</select>-->
</div>

Loop through a complex JSON structure using AngularJS

I can access my desired field from a JSON object like so:
<li ng-repeat='customer in customers[0][data]["DisplayName"] | filter:search'>{{ customer }}</li>
However, that only returns one object's property.
Using AngularJS, is there a way to loop through the following?
customers[0][data]["DisplayName"]
customers[1][data]["DisplayName"]
customers[2][data]["DisplayName"]
customers[3][data]["DisplayName"]
customers[4][data]["DisplayName"]
...
customers is an array, so by doing ng-repeat you will already loop through it. But I think what you want is either: 1) show the DisplayName property inside <li> or 2) filter by DisplayName.
To show the nested property, do the following
<li ng-repeat="customer in customers">
{{ customer[data]["DisplayName"] }}
</li>
To filter on nested property, for example on DisplayName:
<li ng-repeat="customer in customers | filter:{data: {DisplayName: search}}">
...
</li>