How to dynamically apply a tooltip to part of an element's dynamic text content in Angular?

会有一股神秘感。 提交于 2021-02-11 09:45:01

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!