Change span class title based on JSON file data - html

My goal is to generate a tool tip using the title attribute of a span class, but to have the title content change depending on the span class.
Today, I have a JSON file that has an attribute of status, which is represented with status color (e.g. gray, blue, orange, etc). Example:
{
"area":"Grouping",
"title": "Information Architecture",
"link": "#",
"password": "",
"designer": "Some Name Here",
"status": "purple",
"dateupdated": "2019-07-18"
},
Then I use angular to show this data. Here is the status column:
<ng-template
let-row="row"
let-value="value"
#statusColumnTemplate>
<span class="{{ value }}" title="Test title"></span>
</ng-template>
Obviously with this code, no matter what class color is passed in the title will be the same. Ideally, I'd like a different message in the title for each class, but I am unsure how to do this.
Any help is greatly appreciated!

So you have 2 possibilities to achieve that:
You can write your condition directly into the title-tag like this:
<span class="{{ value }}" [title]="value === 'something' ? 'Tooltip on match' : 'Tooltip on else'">
</span>
You can write your entire spans conditionally with an *ngIf structural directive:
<span *ngIf="value === 'something'" class="{{ value }}" title="First Tooltip">
</span>
<span *ngIf="value !== 'something'" class="{{ value }}" title="Second Tooltip">
</span>

Related

Variabilizing the # from <mat-menu>

I'm currently trying to generate a dynamic menu from a JSON blob in my typescript files, Angular project.
I'm using the / component from Angular Material.
My json menu has this structure :
{
id: 0,
titreTranslate: 'menu-accueil',
isDescriptionRequired: true,
routerLink: '/accueil',
icon: faHome,
isAllowed: true,
hasSubOptions: false,
trigger: 'accueil'
}
My code look something like this :
<mat-toolbar-row class="navigation-row">
<span *ngFor="let option of menuOptions">
<button mat-button
[matMenuTriggerFor]="admin"
routerLink="{{option.routerLink}}"
(keyup.enter)="router.navigate([option.routerLink], { queryParams: option.queryParams })"
[routerLinkActive]="['active-menu']"
[queryParams]="option.queryParams"
class="link bouton-menu-gauche flex-row"
*ngIf="option.isAllowed"
>
<fa-icon
*ngIf="option.icon"
class="primary-color"
[icon]="option.icon"></fa-icon>
{{ option.titreTranslate | translate }}
</button>
<mat-menu #{{option.trigger}}="matMenu">
<span *ngFor="let subOption of option.menuOptions">
<button mat-menu-item
*ngIf="option.menuOptions"
routerLink="{{subOption.routerLink}}"
(keyup.enter)="router.navigate([subOption.routerLink], { queryParams: subOption.queryParams })"
[routerLinkActive]="['active-menu']"
[queryParams]="subOption.queryParams"
class="link bouton-menu-gauche flex-row">
<fa-icon
*ngIf="subOption.icon"
class="primary-color"
[icon]="subOption.icon"></fa-icon>
{{ subOption.titreTranslate | translate }}
</button>
</span>
</mat-menu>
</span>
</mat-toolbar-row>
The line with " <mat-menu #{{option.trigger}}="matMenu"> " is what concerns me here ; I've tried many ways to variabilize this #, such as putting it directly in the Json menu or trying different syntax ; It always fail, and won't give me the code structure i want.
If i had to guess, i'd say the generated code should look like : <mat-menu #"accueil"="matMenu">, with "" that fail to compile ; but i don't get any compilation errors, so i'm lost here.
Does anybody had to work with that kind of structure before ?
(apologies for my english if it's bad, i'm french)
Check out this answer:
https://stackoverflow.com/a/44441164/2025458
It's easier to search for the answer if you call things by the name they are given in the documentation, the '#' is a template reference or template variable
And since it's inside a structural directive (*ngfor or any other directive strating with *)
It binds to a template created by the structural directive, so every loop of the ngfor generates its own nested template with its own instance of the variable, so you can just use one name

Loop items with higher click_count first

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.

Locales/literals containing html

In
locale/lang.json I have
{
"title": "Title",
"image": "service-corporate_thumb-v2.jpg",
"alt": "alt",
"imageFooter": "Some caption %",
"imageFooterCTA": "author",
"imageFooterURL": "https://example.com/author",
},
I'm trying to generate the author like, like so:
<img :src="require(`~/assets/img/services/${service.image}`)" :alt="service.alt" class="mb-8">
<p>{{ service.imageFooter.replace('%', `${service.imageFooterCTA}`) }}</p>
But this prints out in the generated HTML:
{{ service.imageFooter.replace('%', `${service.imageFooterCTA}`) }}
How can I generate html inside the {{ expresion }} ?
You need to use v-html for generating html in a template.
More info here.
For your example try this
<p class="mb-8">
<a v-html="service.imageFooter.replace('%', '$' + service.imageFooterCTA + '')">
</p>
Notes:
the tag that has a v-html directive will be replaced, so you could use anything, not only a
the value for v-html needs to be valid JS code that will be executed in the current context. This the reason I treated the tag inside as a string and removed the interpolation {.

Angular ng-repeat sort into several divs

I have a some code that currently displays all my items and sort them by icon.
<li ng-repeat="availableItem in model.availableItems | compareArrays:model.selectedItems:'alias' | orderBy:'icon' | filter:searchTerm"
ng-click="selectItem(availableItem)"
class="-three-in-row">
<a class="umb-card-grid-item" href="" title="{{ availableItem.name }}">
<i class="{{ availableItem.icon }}"></i>
{{ availableItem.name }}
</a>
</li>
My goal is to create a div for each icon type (categories) and place them inside the div how can I do that in angular? I have tried with ng-if but cant get it to work the way I want to. Desired output would look something like this
You can use groupBy filter and apply css accordingly to each li tag.
<ul ng-repeat="(key, value) in stuff | groupBy: 'category'">
category name: {{ key }}
<li ng-repeat="item in value">
item: {{ item.name }}
</li>
</ul>
Also https://github.com/a8m/angular-filter is a great resource as well that allows you to do more outside AngularJs box.
I believe this is what you need:
How can I group data with an Angular filter?
All you need to do is to substitute the key with the div for your icon group.

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