Reputation: 1408
I'm trying to write a function to be used within [ngClass]
to apply a CSS class to certain characters within a larger string. which are returned from a 3rd party API.
Let's say the returned data is like this:
data = [
{ name: 'Johnny', description: "Johnny ate an apple."},
{ name: "Bobby", description: "Bobby hates apples."}
]
My HTML will loop through all objects in the data array and print them to the UI. BUT, I need to search each description property on each object and find out if there's an exact match and apply the style to just that word.
Therefore, I need to compare two strings, character by character.
Let's say the class is 'text-italics
'. Which case the CSS would look like this:
.text-italics {
text-transform: italics !important;
}
And my string is "Johnny ate an apple." from the description property of object one.
But I only want "apple" italicized. Not the "a" in 'ate' or the 'a' in 'an'.
Same for object two. "apple" of "apples" should be italicized. Not the "a" in "hates".
<ng-container *ngFor="let char of item.description | splitString ">
<span [ngClass]="{'text-italics' : applyItalics(item.descripton, b)}">
{{char}}
</span>
</ng-container>
I'm attempting to write a function that would be used within [ngClass]. I'm thinking I'll have broken the strings down into character arrays with .split('')
and then loop through each character in the HTML?
I'm playing around with a function like this, but once I know that the term the user searched for is in the termToCheckAgainst
, I need to apply the style to each character that is an exact match:
applyItalics(nameOfData: string, termUserSeachedFor: string): boolean {
nameOfData = nameOfData.toUpperCase();
termUserSeachedFor = termUserSeachedFor.toUpperCase();
return nameOfData.includes(termUserSeachedFor);
}
Upvotes: 1
Views: 692
Reputation: 3440
If you want to style character by the character being part of a complete search term than you need to pass an index of the character in the description, such as let char of outerItem.description | splitString; let i = index;
and use some algorithm to check the characters are part of the search term. Since we are normalizing to upper case, I use a lower case letter "a" for this.
//our root app component
import { Component, NgModule, VERSION } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { splitStringPipe } from './split-string.pipe';
@Component({
selector: 'my-app',
template: `
<div>
<dl>
<dt>Term</dt>
<dd><input [(ngModel)]="b" /></dd>
</dl>
<ng-container *ngFor="let outerItem of data">
<ng-container *ngFor="let char of outerItem.description | splitString; let i = index;">
<span [ngClass]="{'text-italics' : applyItalics(outerItem.description, i, b)}">
{{char}}
</span>
</ng-container>
</ng-container>
</div>
`,
})
export class App {
data: object[];
b: string;
constructor() {
this.b = "term";
this.data = [
{ name: 'Johnny', description: "Johnny ate an apple."},
{ name: "Bobby", description: "Bobby hates apples."}
];
};
applyItalics(desc,i,b) {
if (desc) {
let normalDesc = desc.toUpperCase();
let normalTerm = b.toUpperCase();
let tTerm = normalDesc.replace(normalTerm,Array(normalTerm.length+1).join("a"));
return tTerm[i] === 'a';
}
return false;
}
}
@NgModule({
imports: [BrowserModule, FormsModule],
exports: [splitStringPipe],
declarations: [splitStringPipe,App],
bootstrap: [App],
})
export class AppModule {}
Here is the full example on Plunker https://embed.plnkr.co/plunk/pXhbQbZhDnM1jNZ7
Upvotes: 0
Reputation: 2964
You don't need to have two separate functions for this, just contain everything in the pipe:
@Pipe({
name: 'wrapItalic'
})
export class WrapItalic {
transform(content, word) {
const splits = content.split(' ');
let result = '';
splits.forEach(next => {
word === next ? result += ` <i>${next}</i> ` : result += ` ${next}`;
});
return result.trim();
}
}
And your HTML:
Test <span [outerHTML]="'Jonny ate an Apple' | wrapItalic: 'Apple'"></span>
It is possibly quicker as you're only doing the work (loop) once
Upvotes: 2