I have this simple Angular Component:
@Component({
selector: 'my-component',
template: '<p>{{someString}}</p>',
})
export class MyComponent {
@Input() someString: string;
}
someString
could be any string of any length. As an example, imagine that someString
's value is :
"If you want my body and you think I'm sexy, come on, sugar, tell me so."
In that case the HTML generated by Angular would essentially be equivalent to:
<p>If you want my body and you think I'm sexy, come on, sugar, tell me so.</p>
How would I modify MyComponent
so that it detects each occurrence of the word sexy
in someString
and have Angular wrap that word in another HTML element such as <b>
. So in this example case it would generate something like:
<p>If you want my body and you think I'm <b>sexy</b>, come on, sugar, tell me so.</p>
What if I wanted to wrap every occurrence of the word sexy
in an Angular Component instead of a native HTML Element? Would that necessitate a different approach?
This solution avoids using innerHTML
and relies strictly on Angular constructs.
@Component({
selector: 'my-component',
template: `
<p>
<ng-container *ngFor="let segment of segments">
<span *ngIf="!segment.shouldBeBold()">segment.text</span>
<b *ngIf="segment.shouldBeBold()">segment.text</b>
</ng-container>
</p>
`,
})
export class MyComponent {
@Input() someString: string;
private wordsToBold = new Set(['sexy', 'body', 'sugar']);
get segments() {
const regex = this.makeRegex();
const segments = this.someString.split(regex);
return segments.map(segment => {
return { text: segment, shouldBeBold: wordsToBold.has(segment.toLowerCase()) };
});
}
private makeRegex() {
const expression = [...this.wordsToBold].join('\\b|\\b');
return new RegExp(`(\\b${expression}\\b)+`, 'gi');
}
}