I have an array of months. for some reason angular for loop does not follow the order of the array.
How can that be fixed?
#Component({
selector: 'my-app',
template: `<div *ngFor="let item of collection | keyvalue; index as i">{{item | json}}</div>`,
})
export class AppComponent {
collection : {key : any, value : any}[] = [];
constructor(){
let i = 0;
for(let month of moment().locale('en-US').localeData().monthsShort()){
i++;
this.collection.push({key : i,value : month});
}
}
https://stackblitz.com/edit/angular-i25npn?file=src%2Fapp%2Fapp.component.ts
According to the definition of keyvalue from the docs.
The output array will be ordered by keys. By default the comparator
will be by Unicode point value...
And therefore your keys(string) are ordered by default.
Remove the pipe | keyvalue; index as i from your *ngFor.
To follow the order, replace:
<div *ngFor="let item of collection | keyvalue; index as i">{{item | json}}</div>
by:
<div *ngFor="let item of collection">{{item | json}}</div>
Related
I am testing out
[NgForOf]
of angular, but it only works if my function literally returns ['a', 'b', 'c'].
It does not work if my function returns string[]. How can make
[NgForOf]
works if I have a function returning string[] as its result?
The following is my app.component.html file’s content:
I am testing out [NgForOf], but it only works if my function literally
returns ['a', 'b', 'c']. It does not work if my function returns
string[]. How can make [NgForOf] works if I have a function returning
string[] as its result?
------------- Why Output from getNamesA() does NOT loop?
------------------ <ng-template ngFor let-name [NgForOf]="namesa" #getNamesATemplate> output from getNamesA() :
<ng-container *ngFor="let namesfroma of
getNamesA()" [ngTemplateOutlet]="getNamesATemplate"
[ngTemplateOutletContext]="{namesa: namesfroma}">
------------- Output from getNamesB() does loop ------------------ <ng-template ngFor let-name [NgForOf]="namesb"
#getNamesBTemplate>
output from getNamesB() : <ng-container *ngFor="let namesfromb of getNamesB()" [ngTemplateOutlet]="getNamesBTemplate"
[ngTemplateOutletContext]="{namesb: namesfromb}">
------------- Output from getNamesC() does loop ------------------ <ng-template ngFor let-name [NgForOf]="namesc"
#getNamesCTemplate>
output from getNamesC() : <ng-container *ngFor="let namesfromc of getNamesC()" [ngTemplateOutlet]="getNamesCTemplate"
[ngTemplateOutletContext]="{namesc: namesfromc}">
The following is my app.component.ts file’s content: import {
Component } from '#angular/core';
#Component({ selector: 'app-root', templateUrl:
'./app.component.html', styleUrls: ['./app.component.css'] }) export
class AppComponent { title = 'demo';
public getNamesA (): string[] {
var namesA: string[] = [];
var namesB = ['Tom', 'Lis', 'Peter'];
namesB.forEach (x=>namesA.push(x));
return namesA; }
public getNamesB (): string[] {
var namesB = ['Tom', 'Lis', 'Peter'];
return namesB; }
public getNamesC (): string[] {
return ['Tom', 'Lis', 'Peter']; } }
The following is the output web page of my testing app: I am testing
out [NgForOf], but it only works if my function literally returns
['a', 'b', 'c']. It does not work if my function returns string[]. How
can make [NgForOf] works if I have a function returning string[] as
its result?
------------- Why Output from getNamesA() does NOT loop? ------------------
------------- Output from getNamesB() does loop ------------------ output from getNamesB() : output from getNamesB() : output from
getNamesB() :
------------- Output from getNamesC() does loop ------------------ output from getNamesC() : output from getNamesC() : output from
getNamesC() :
------------------------------------------------------------------ What can I change in GetNamesA() for [NgForOf] to loop? In order
others, how can convert string[] into [string, string, string, ...].
Example, string[] into ['a', 'b', 'c'] In another wording, how can I
make getNamesA() to return result as getNamesB() and get getNamesC()
in TypeScript or in Angular? Thank you very much for your help in
advance.
I have attached my screenshots of my testing app files.
screenshot1screenshot2screenshot3
Thank you for your hel2p in advance.
TM
I'm trying to create a dynamic array based on an integer, so, assuming integer i = 3, it would create an array with length 3.
counter (i: number) {
return new Array(i);
}
Why does this return an array with length 1 and a member with a value of i rather than an array with length i?
EDIT:
A walkaround to what I'm trying to do is:
counter (i: number) {
var a = new Array();
for (var x = 0; x < i; x++)
a.push(x);
return a;
}
I'm just curious about the behavior of the array constructor.
By testing your example with angular core 5.0.0, the function will create an array with length 4 for example, and when you do the resulting variable.length it will equal to 4. so, the given link before has all what you need to understand the result.
here is a demo that demonstrate that:
https://stackblitz.com/edit/angular-9effym?file=app%2Fapp.component.html
(direct link, for debugging with dev tools: https://angular-9effym.stackblitz.io)
result
Hello !
Array length: 4
value 0 = undefined
value 1 = undefined
value 2 = undefined
value 3 = undefined
code:
app.component.html:
<hello name="{{ name }}"></hello>
<div>
<br>
Array length: {{xx.length}}
<br>
<br>
<div *ngFor="let value of xx; let i = index">
value {{i}} = {{value+''}}
</div>
</form>
<br>
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
xx:any;
ngOnInit() {
this.xx = this.counter(4);
}
counter(i: number){
return new Array(i);
}
}
Note:
since we didn't initialize the elements of the array, there content will be undefined, I demonstrated that by converting the content to string using {{value+''}} in the template
I'm using Angular2 and I have retrieved some data from Firebase in this way:
dataset: any;
onGetData() {
this._dataService.getAllData()
.subscribe(
data => this.dataset = JSON.stringify(data),
error => console.error(error)
);
if I print dataset I get this JSON:
{"-KE8XuCI7Vsm1jKDJIGK":{"content":"aaa","title":"bbb"},"-KE8XvM268lWhXWKg6Rx":{"content":"cccc","title":"dddd"}}
How can I print out a list made up of only the title values from this JSON array?
I'd like to have: bbb - dddd
You can only iterate over an array using ngFor. In your case you need to implement a custom pipe to iterate over keys of an object.
Something like that:
#Pipe({name: 'keyValues'})
export class KeysPipe implements PipeTransform {
transform(value, args:string[]) : any {
let keys = [];
for (let key in value) {
keys.push({key: key, value: value[key]);
}
return keys;
}
}
and use it like that:
<span *ngFor="#entry of dataset | keyValues">
Title: {{entry.value.title}}
</span>
See this question for more details:
How to display json object using *ngFor
In your view you need
<div *ngFor='#data of dataset'>
{{ data.title }} -
</div>
I use angular-filter in my project to sort the output objects by page the problem is when I use syntax like this:
<ul class="catalog-list"
ng-repeat="(key, value) in list | groupBy: 'styl' | toArray | orderBy:'page'">
{{key}}
<li ng-repeat="dziecko in value | filter:search | bookmark:search"
ng-class="{active:isActiveTab(dziecko)}"
ng-click="openItem(dziecko)">
{{dziecko.rodzina}}
<b>{{dziecko.page}}</b>
</li>
</ul>
Angular converts 'styl' properties ['nowoczesny','klasyczny'..] to numbers. Sorting works fine but I want to obtain names instead of numbers.
groupBy return an object, and orderBy expect array as an argument, so that's the reason you should use toArray filter.
toArray work like that:
Usage: object | toArray: addKey[optional]
if addKey set to true, the filter also attaches a new property $key to the value containing the original key that was used in the object we are iterating over to reference the property
So, you can do something like this example, or take a look on the jsbin
JS:
$scope.groups = [
{ category: 'alpha', id: 2 },
{ category: 'beta', id: 3 },
{ category: 'gamma', id: 0 },
{ category: 'alpha', id: 4 },
{ category: 'beta', id: 5 },
{ category: 'gamma', id: 1 }
];
HTML:
<ul ng-repeat="group in groups | groupBy:'category' | toArray:true | orderBy:min">
<!-- print the group name -->
<li>{{ group.$key }}</li>
<!-- iterate over the group members and order each group by id -->
<li ng-repeat="item in group | orderBy:'id'">
{{ item }}
</li>
</ul>
RESULT:
alpha
{"category":"alpha","id":2}
{"category":"alpha","id":4}
beta
{"category":"beta","id":3}
{"category":"beta","id":5}
gamma
{"category":"gamma","id":0}
{"category":"gamma","id":1}
An array has no named keys. It has integers as position. So don't use toArray.
I have an object that maps IDs to their objects. I would like to display the list of these object and use a filter, but I cannot get it to work. Specifically, I'm trying to prevent object with ID 2 from appearing in the options Here's what I've got:
http://jsfiddle.net/9d2Za/
<div ng-app ng-controller="ctrl">
Unfiltered:
<select ng-model="selectedBidType"
ng-options="bidType.id as bidType.label for (bidTypeID, bidType) in bidTypes">
</select>
<br>
Filtered:
<select ng-model="selectedBidType"
ng-options="bidType.id as bidType.label for (bidTypeID, bidType) in bidTypes | filter:{id: '!2'}">
</select>
</div>
Please note: I cannot change the structure of the bidTypes object in whatever fix we come up with. Here's my AngularJS:
function ctrl($scope)
{
$scope.selectedBidType = 1;
// Bid type objects are indexed by ID for fast lookup (this cannot be changed in solution)
$scope.bidTypes = {
1: {id: 1, label: "Buy"},
2: {id: 2, label: "Sell"},
3: {id: 3, label: "Missing"}
};
}
As described by the documentation, the filter filter only accepts an array as first parameter, not an object. In such cases, I personally use a custom filter to make the transformation:
myModule.filter(
'objectToArray',
[
function ()
{
return function (object)
{
var array = [];
angular.forEach(object, function (element)
{
array.push(element);
});
return array;
};
}
]
)
;
And then, in the template:
<select ng-options="… in bidTypes | objectToArray | filter:{id:'!2'}">