问题
So I have this json file containing a dictionary.
definitions.json
{
"word": "Some definition.",
"an expression": "Some other definition."
}
And I have components throughout my app that may be similar to this.
my.component.ts
@Component({
selector: 'my',
template: `
<h1>{{ someTitleText }}</h1>
<p>{{ someText }}</p>
`
})
export class MyComponent {
@Input() someTitleText: string;
@Input() myText: string;
}
I want to display a tooltip when the user will hover over a word that is present in the dictionary file and I need the tooltip to display the corresponding definition.
Making a parsing function to detect if and where a word or expression is present in a string is relatively trivial. Where I specifically need help is in figuring out the Angular way of adding the tooltip behavior to that specific word or expression inside the element once it has been detected.
ngx-bootstrap already has a tooltip and I would like to use that one rather than implement one from scratch.
What I need is the ability to somehow (structural directive, attribute directive, pipe, other???) selectively designate elements all over my app as having this behavior.
In other words, I need a reusable way to tell Angular "Hey, this element right here, I want you to check if it has some text content, and if some of that text is present in my dictionary, and if it is I want you to make it possible for the user to hover over that word or expression and for a tooltip to appear containing the appropriate definition for that word or expression."
回答1:
It is easy to create an Angular component dynamically at run-time compared to an Angular directive. All you have to do is to create a wrapper Angular component (say, TooltipComponent
that takes 2 inputs namely displayText and tooltipText) that applies the ngx-bootstrap tooltip directive to some HTML element of your choice. Then render this wrapper component dynamically for the word that is present in your dictionary.
I believe everything in the below code snippet is self-explanatory.
app.component.ts
@Component({
selector: "demo-tooltip-basic",
template: `<p #para></p>`
})
export class AppComponent implements AfterViewInit {
@ViewChild("para", { static: false }) para: ElementRef<HTMLElement>;
text = `I'm in love with the shape of you!`;
dict = {
love: "like something",
shape: "blah!!!",
something: "..."
};
...
ngAfterViewInit() {
this.text.split(" ").forEach(word => {
if (this.dict[word]) {
let factory = this.resolver.resolveComponentFactory(TooltipComponent);
let ref = factory.create(this.injector);
ref.instance.text = `${word} `;
ref.instance.tooltip = this.dict[word];
ref.changeDetectorRef.detectChanges();
this.renderer.appendChild(
this.para.nativeElement,
ref.location.nativeElement
);
} else {
this.renderer.appendChild(
this.para.nativeElement,
this.renderer.createText(`${word} `)
);
}
});
}
}
To view the complete code of this app, use this stackblitz link (https://stackblitz.com/edit/dynamic-tooltips).
I hope you can further improve this basic implementation to suit your needs. For more information on creating Angular components dynamically, view this article.
Note: It is recommended to use Renderer2
API provided by the Angular to safely create HTML elements at runtime.
来源:https://stackoverflow.com/questions/60284184/how-to-dynamically-apply-a-tooltip-to-part-of-an-elements-dynamic-text-content