Loop items with higher click_count first - html

I am making a recent search results component. In this component im taking search results from the API, and there is a value called "click_count". Every time someone get a positive result from the recent search that was clicked this value will increase by one.
Now I want to show the ones with the highest click_count first. Anyone knows how this is possible?
HTML
<ng-container *ngFor="let recent of searchSrvc.displayRecents | slice:0:5; let i=index">
<div class="result-row-wrapper">
<div class="icon-row-wrapper recents">
<ng-container>
<i class="fas fa-clock" (click)="setRecent(recent)"></i>
<p class="label" (click)="setRecent(recent)">{{ recent.search_text }}</p>
</ng-container>
<ng-container *ngIf="recent.user_id === this.model.id">
<i class="own-search fas fa-times" (click)="deleteSearch(i)"></i>
</ng-container>
</div>
</div>
</ng-container>
TS
The typescript just consists of an array im calling with multiple items that look like this:
{
archived: "0"
atime: null
auser: null
click_count: "0"
ctime: "1633514604"
cuser: "Dev Gebruiker"
id: "7"
mtime: "1633514604"
muser: "Dev Gebruiker"
organisation_id: "31"
resource: "building"
results_count: "0"
search_text: "add e"
ucurrency: "EUR"
user_id: "1"
},

Changing the order of items in an array is called sorting. The Array prototype already contains a method to sort, Array#sort.
const sortedArray = [...array].sort((a, b) => {
return Number(b.click_count) - Number(a.click_count)
})
Now use this sortedArray in your template with a regular *ngFor.

Related

Using Typescript Variable to create img src

I have an array which contains a list of categories, below is an example of one category:
description: "test"
[0]
icon: "assets/images/test1"
name: "test"
[1]
icon: "assets/images/test2.png"
name: "test 2"
I am trying to loop through this array and display both the category name and the icon, however, displaying the icon isn't working.
<ng-container *ngFor="let category of this.categories>
{{category.name}}
<img src={{category.icon}}/>
</ng-container>
Does anyone know how to do this? Thanks
I'm not an angular expert, but shouldn't you use the [] syntax for property binding?
E.g.:
<ng-container *ngFor="let category of this.categories">
{{category.name}}
<img [src]="category.icon"/>
</ng-container>
Also, you're missing a " at the end of categories.

get result from array of objects retrieved from db and return to ng-template

I have a complex array of objects retrieved from db
Link to the Code
let arr = [
{
"userId": "-jgtgjS",
"firstName": "def",
"lastName": "yellow",
"email": "def#gm.com",
"otp": 0,
"otpExpiry": "",
"mobileNumber": 9852145987,
"createdOn": "2019-09-15T11:50:29Z",
"gender": "female",
"profilePic": "",
"friendList": {
"_id": "5d7e25852fffaa2858930878",
"userId": "-jgtgjS",
"friendCount": 0,
"userObject": "5d7e25852fffaa2858930877",
"allFriends": [
{
"friendId": "GsbItTr",
"requestSent": true,
"requestReceived": false,
"friendSince": 1568549711731,
"_id": "5d7e2b2f25207f161c718a64",
"friendObject": "5d7e285aa6132b179cfa917c"
},
{
"friendId": "ch4PXXn",
"requestSent": false,
"requestReceived": true,
"friendSince": "",
"_id": "5d7f16124c7b3f16ec308c1d",
"friendObject": "5d7dce8d2a719a1d188ed641"
}
],
"__v": 2
}
}]
Link to the Code
I am using *ngFor to display the friends in my template, but I also need to show whether he is friend or not, how can I pass the instance of *ngFor before display to .ts and then compute the boolean and then return back to the template so that the user displayed is friend or not.
Added a pic. Now the button shows add friend in each using ngFor. but depending on the status of each user the button would change to accept if a request is received or it will show friends if the request is already accepted and friendSince has some value
I am able to get the status like this.
ar[0].friendList.allFriends.forEach(element=>{
if (element.friendId=='ch4PXXn'){
sent=element.requestSent;
received=element.requestReceived;
}
});
if u refer to the image added.. u can see there are many users listed in the view using *ngfor. 'def yellow' is one of them. Now inside of users object there is another array of objects which stores all the friend request transactions happening. This view is being seen by userId 'ch4PXXn'. So I need to find the object inside allFriends with a friendId containing ch4PXXn and then based on other parameters like sent, received, since. I want to show a button which will give user ch4PXXn options to accept or show request sent.
Link to the Code
Try like this:
<div *ngFor="let friend of arr">
<h3>{{friend.firstName}} {{friend.lastName}}</h3>
<h4>{{friend.gender}} </h4>
<h5>{{friend.email}} </h5>
<h5>{{friend.mobileNumber}} </h5>
<table>
<tr>
<th>Friend Id </th>
<th>Is Friend </th>
</tr>
<tr *ngFor="let item of friend.friendList.allFriends">
<td>{{item.friendId}}</td>
<td>{{item.friendSince == '' ? 'Not Friend' : 'Friend'}}</td>
</tr>
</table>
</div>
Working Demo
You can use a nested *ngFor, where you iterate the allFriends array, and based on your conditions show different content:
<ng-container *ngFor="let a of friend.friendList.allFriends; let last = last">
<!-- First check that friend matches the current user -->
<div *ngIf="a.friendId === loggedInUser">
<!-- are you already friends? -->
<p *ngIf="a.friendSince">You are friends!</p>
<!-- You have received a request, but not yet accepted -->
<button *ngIf="a.requestReceived && !a.friendSince> Accept Friend request</button>
<!-- You have sent request, but user hasn't accepted -->
<button disabled *ngIf="a.requestSent && !a.friendSince">Friend Request Sent</button>
</div>
<!-- All above conditions are false, and it is last item in array -->
<button *ngIf="a.friendId !== loggedInUser && last">Add Friend</button>
</ng-container>
Here's a STACKBLIZ

How to iterate over single character in a string

How can I iterate a string using the *ngFor?
I have a string with binary code (e.g. 0010) and dependendig on a single bit I have to show a different icon.
<div class="row" *ngFor="let item of subscribedCommandBus2Easy; let i = index">
<span class="numberCircleBus2Easy col-md-2">
{{item}}
</span>
<i *ngFor="let num of commandsDecimal">
<i ng-repeat="let el in num">
<span [ngClass]="el =='0' ? 'off-icon' : 'on-icon'">
//is this the way I access the single character?
</span>
</i>
</i>
</div>
I tried this code but it does not work.
commandsDecimal is my array of binary string. I want to loop commandsDecimal at index i (suppose the element is 1010) and if the character at position y is 0 I have to show an icon otherwise the other icon and so on...
Any suggestion?
The best way is to do a split on your string. With a custom pipe:
#Pipe({
name: 'split'
})
export class SplitPipe implements PipeTransform {
transform(value: any, args?: any): any {
return value.split('');
}
}
And then iterate over it. like that:
<div *ngFor="let item of myString">
<div *ngFor="let num of item | split item">
// access num
</div>
</div>
Example: https://stackblitz.com/edit/angular-8bkywr
In your component typescript
function getSplit(string) {
return string.split('').map(number)
}
In the template
*ngFor="let num of getSplit(commandsDecimal)"
You can do this without the need for any code in your component. Also ng-repeat is AngularJS syntax, not Angular 2+. In Angular 2+, ngFor is used to iterate in the HTML.
<ng-container *ngFor="let num of commandsDecimal">
<i *ngFor="let el of num.split('')" [ngClass]="el === '0' ? 'off-icon' : 'on-icon'"></i>
</ng-container>

angular 2 ngFor Cannot read property of undefined

I have a nested object with data that I am trying to access with ngFor.
I am able to reach the first part of the data with the first ngFor (app_name, time_stamp etc)
But for some reason I am not getting to the nested object of test_cases. When I try it breaks the whole page and the console keeps telling me "Cannot read property 'test_cases' of undefined" and I can't seem to figure out why...
(first part of) data inside the component:
export class AppComponent {
tests = TESTS;
var TESTS: Test[] = [
{
"app_name": "website",
"time_stamp": "2018-01-20T12:00:00Z",
"test_cases": [
{
"test_name": "View article",
"status": true,
}]
}]
HTML partial:
<div id="tested-app" *ngFor = "let item of tests">
<h2>----<span> {{ item.app_name }} </span>----</h2>
<p id="time"> Time: <span> {{item.time_stamp}} </span> </p>
</div>
<div class="module" *ngFor="let subItem of item.test_cases">
<h3>{{subItem.test_name}}</h3>
</div>
For peeps who are struggling with this:
John Montgomery and Andres M answered this in the comments, I had to put the second div inside the first.

ng repeat does not return variable from JSON file

I have the following html code that belongs to a template in AngularJS framework:
<ul class="sb-parentlist">
<h1 class={{headerClass}}> Popular</h1><div data-ng-repeat="data in data track by $index">
<li>
<span class="sb-text-title" href="#" ng-click="openFaq = ! openFaq"><b>{{data[$index].faq.frage |translate}}</b></span>
<span ng-show="openFaq" class="sb-text">
<br>
{{data[$index].faq.antwort |translate}}
</span>
</li>
</div>
</ul>
I am getting the number of "li" elements on my browser correctly on printing the results, but the variables are not defined as they should be, blank entries appearing.
here is the JSON entry:
{
"faq":
{"frage":"HB_START_FAQ_Q",
"antwort":"HB_START_FAQ_A"}
,
"screencast":"HB_START_SCREENCAST"
},
{
"faq":
{"frage":"HB_START_FAQ_Q_1",
"antwort":"HB_START_FAQ_A_1"}
,
"screencast":"HB_START_SCREENCAST_1"
},
{
"faq":
{"frage":"HB_START_FAQ_Q_2",
"antwort":"HB_START_FAQ_A_2"}
,
"screencast":"HB_START_SCREENCAST_2"
},
{
"faq":
{"frage":"HB_START_FAQ_Q_3",
"antwort":"HB_START_FAQ_A_3"}
,
"screencast":"HB_START_SCREENCAST_3"
}
I am interested to get the nested item. Any ideas?
Because data is ambiguous between the collection name and the item being iterated over - change your ngRepeat syntax:
data-ng-repeat="item in data track by $index"
And use item[$index]. Im not entirely sure why you aren't just doing data.faq - you need to select by the $index