I'm trying to display data within my dataset on my angular front end. Some info i want to display is nested within an Object Object. As you can see below. I'm having trouble displaying the lat and long values. I have tried this html:
<ng-container *ngFor="let geometry of trail?.geometry">
<ng-container *ngFor="let location of geometry?.location">
<ng-container *ngFor="let lat of location?.lat">
{{ lat }}
</ng-container>
</ng-container>
</ng-container>
If I understand you need to display the lat in the html, but in your code you are trying to iterate an object and that is not possible in this case, for display the lat in your html you only need to access to the key lat in your object, like this:
<ng-container>
{{ geometry.location.lat }}
</ng-container>
If you need to show the ng-container when the lat have a value, you need to validate with *ngIf.
I hope this can be useful for you.
Related
I am using MatDialog and UntypedFormGroup. So from bookcomponent I am either adding new book or editing existing one. I am using same form to edit as well as add new book. For this particular form I am getting authors as observable for firestore and using in the mat-select and storing id of the author in book document like code below
<mat-form-field appearance="fill" *ngIf="author$ | async as authors">
<mat-label>Choose Author</mat-label>
<mat-select formControlName="authorId">
<mat-option *ngFor="let author of authors" [value]="author.id">
{{author.name}}
</mat-option>
</mat-select>
</mat-form-field>
This is working wonderfully in editing and adding new data.
Edit: I want to get selected {{author.name}} with {{author.id}} from above code. Sorry I question was ambiguous.
I am using mat-table in booklistcomponent and I want to have a column named author. I already share certain data from parent to children i.e bookcomponent<>booklistcomponent<>bookformcomponent by using #input() emitter() and MatDialog.
I tried using ngModel but it is not providing desired result. Is their any way I can use my existing code but also can get author.name value as well without any major change in editing or adding new book code. I am stuck on this one for days now please help. Thanks in advance
I often use .slice().reverse() in *ngFor to display elements in reverse order. But now I have a problem, because I also use | keyvalue. How to use .slice().reverse() with | keyvalue?
<div *ngFor="let order of orderData.order.slice().reverse() | keyvalue ">
Sum: {{order.value.sum}}
</div>
This solution works but I am getting an error:
I don't think that you issue is with the keyvalue pipe. Probably the orderData is still not loaded whenever you are trying to use it and order is undefined.
You can do optional chaining/safe navigation operator in templates and adding a ? checks to see if the item on the left side has this property and and if it does it just returns it, if it doesn't it returns undefined and in this case if order is undefined inside the pipe transform method as value you will get undefined and if it exists you will get your array.
<div *ngFor="let order of orderData.order?.slice()?.reverse() | keyvalue ">
Sum: {{order.value.sum}}
</div>
Or you can just check if orderData has the order array and then render using the ngIf directive.
I suggest that you don't do slice().reverse() inside the templates like this because on every change detection cycle you will be creating a new array and reversing it. It would be a good idea to create a new pure pipe called reverse that reverses the array only if the instance has changed because otherwise you might get in trouble when working with larger arrays. Also if you are working with larger arrays providing a TrackByFunction on the ngFor will also increase performance.
I think the problem is here orderData.order, is undefined. That's why it throwing that error. You can make sure orderData.order is present then iterate the list like the below.
Note: ng-container is just a wrapper and Angular doesn't put it in the DOM.
<ng-container *ngIf="orderData.order">
<div *ngFor="let order of orderData.order.slice().reverse() | keyvalue">
Sum: {{order.value.sum}}
</div>
</ng-container>
We can get the last entries of the array by specifying the number inside slice with reverse function.
<div *ngFor="let order of orderData.order?.slice(-10)?.reverse() | keyvalue ">
Sum: {{order.value.sum}}
</div>
I want to display some data from a json but i can't simply add an offset to the index and show all te data from a certain offset but get
ERROR TypeError: Cannot read property 'id' of undefinedand the text in the div doesn't appear.
I have already tried to directly add a fixed number in the html file and it works (see the code below). But when it comes to use a variable "offset" (type:number) from typescript that is supposed to be updated with an input, the return type becomes undifined and the error appears. I also tried to use a method in my typescript file instead of doing the addition in the html file, and return the new index but it doesn't work and show the error. I also tried to call the method using {{addition(i,offset)}} and put the result in a variable that I use as an index but it still showing the error.
For exemple, this html file is working fine :
<ng-container *ngFor="let article of data; let i = index">
<ng-container *ngIf="i<(nbElements)">
<div (click)="checkArticle(data[(i+3)].id)">
<p class="text-center"> {{data[(i+3)][dataKey]}}</p>
</div>
</ng-container>
</ng-container>
The div reacts to my click and the text appears.
However, this html file is not working, even if the offset is set as 3 (as the html above) using an input in the parent component :
<ng-container *ngFor="let article of data; let i = index">
<ng-container *ngIf="i<(nbElements)">
<div (click)="checkArticle(data[(i+offset)].id)">
<p class="text-center"> {{data[(i+offset)][dataKey]}}</p>
</div>
</ng-container>
</ng-container>
The error appears.
The offset (type:number) is defined in my typescript file this way, and is changed by the parent component and can easily be displayed by the child component using console.log(offset):
export class AppColumnComponent implements OnInit {
#Input() offset : number ;
I expect the output to be texts showing the articles of my data json, but as I change the offset using an input like that data[(i+offset)] the result is an error, maybe it's impossible to use an other index using an other variable that a fixed number ?
Thank you for your support, it's my first post on stackoverflow i hope i did it well ! :)
If you want to make a pagination component, you should not rely solely on your HTML and some bindings.
Your component should have an "advanced" logic, in the sense that it should be able to know when it reaches the end/start of the collection (among other things).
Basically, this goes as follow :
Get the full collection (let's say 100 items)
Splice it to your item per page number (let's say 10, so results range is 0-10)
Test if items exist before the range
Test if items exist after the range
Allow/block page changing based on those variables.
This leaves you with
1 variable for the collection
1 variable (or 1 pipe) for the subset of the collection
1 variable for the items per page number
1 variable for the offset
2 booleans to disable pagination buttons.
Try working with this, and if you still have issues, then please provide a stackblitz with what you have tried !
You are accessing an index out of bounds.
data[(i+offset)] will be undefined for the last offset amount of elements in your data array so you are basically trying to do undefined.id which leads to your error.
You should change your method signature to only recieve the index as parameter and handle that case in your component.ts file
This question already has an answer here:
Where does Angular define "as local-var" behavior for *ngIf?
(1 answer)
Closed 4 years ago.
I have a question about declaring temporary variables in Angular template to use it for multiple element (childs) like: (Idea / Expected)
<ng-container *ngVar="let theValue = item.getValue()">
<div>{{ theValue }}</div>
<div [class.foo]="theValue == 42">foo</div>
</ng-container>
I already have a workaround for this. Just wrap the value in a array and use ngFor like: (Workaround)
<ng-container *ngFor="let theValue of [item.getValue()]">
<div>{{ theValue }}</div>
<div [class.foo]="theValue == 42">foo</div>
</ng-container>
But this is a bit dirty. - Is there an official solution?
My idea is to reduce the computing of the value over and over again for the same value. I just want to reuse the computed value for multiple childs and / or attributes.
I do not want to compute getValue() every time. Because I get the same value anyway. To hold the value temporary in a group element it can improve the performance and readability.
It should be possible without a custom directive.
I mean to have seen something like this before.
One possible solution is to 'cache' the return value of getValue(). This technique is called memoization. It works only on pure functions, meaning that for the same inputs, the output is always the same, and when function has no side effect.
You can use a decorator to achieve this in a straightforward manner, here is a project that might be useful to you: https://github.com/darrylhodgins/typescript-memoize.
I am new to Angular6 and I wanted to know if there is a simple way to do what I want.
I just read documentation and I did not read anything about that, is there a easy way to sort the value in the dropdown ?
<mat-form-field>
<mat-select placeholder="Code List" required [(ngModel)]="contextScheme.codeListId">
<mat-option *ngFor="let codeList of codeLists" [value]="codeList.codeListId">
{{codeList.codeListName}}
</mat-option>
</mat-select>
</mat-form-field>
Basically the value I have are the values in my DB sorted by id, I want the exact thing but sorted in desc.
Thank in advance.
Sox-.
You should do the sorting either on the database backend side, or as suggested by the Angular team in no order-by pipe it should be done inside the component.
E.g. if your have an array in the component, you could use Array.sort