【问题标题】:Is there any way to make tooltips work via innerHTML?有没有办法让工具提示通过 innerHTML 工作?
【发布时间】:2021-03-19 16:57:35
【问题描述】:

我正在使用属性innerHTML 来编辑标签的内部html,在这个<td></td> 的例子中,但它可以是任何东西:

<td *matCellDef="let order" mat-cell [innerHTML]="order.statusForInterval | statusIcon"></td>

order.statusForInterval 是一个数字,你可以看到我调用管道statusIcon 返回一个字符串,然后绑定到innerHTML。管道如下所示:

@Pipe({name: 'statusIcon'})
export class StatusIconPipe implements PipeTransform {
  transform(statusId: number) {
    switch (statusId) {
      case 0:
        return `<img class="status-icon" src="assets/svg/status-icon/open_icon.svg" alt="up" matTooltip="Open">`;
      case 1:
        return `<img class="status-icon" src="assets/svg/status-icon/progress_icon.svg" alt="up" matTooltip="Progress">`;
      case 2:
        return `<img class="status-icon" src="assets/svg/status-icon/checked_icon.svg" alt="up" matTooltip="Checked">`;
      case 3:
        return `<img class="status-icon" src="assets/svg/status-icon/booked_icon.svg" alt="up" matTooltip="Booked">`;
      case 4:
        return `<img class="status-icon" src="assets/svg/status-icon/error_icon.svg" alt="up" matTooltip="Error">`;
    }
  }
}

因此,根据数字,我返回一个包含img 标记的字符串,然后将其绑定到innerHTML。 一切都按预期工作。我唯一的问题是当我使用innerHTML 属性时工具提示不起作用。如果我以这种方式设置 innerHTML,则属性 matTooltip="Open" 将被忽略。

有什么方法可以让工具提示使用innerHTML 工作?

【问题讨论】:

  • 为什么要更新td,而不是在您的模板中已经有一个带有该类的img 元素,并设置its 值?另外,不要对所有四个图像都使用alt="up":alt 属性用于描述图像所代表的内容,以便辅助工具可以向有部分视力或没有视力的用户描述图像。
  • 你可以看看这个并在你的&lt;td&gt;stackoverflow.com/questions/34504203/…中添加一个&lt;span [outerHtml]&gt;

标签: javascript html angular typescript


【解决方案1】:

我建议你使用两个管道。一个用于图像 src,另一个用于 matToolTip。类似的东西

    <td mat-cell *matCellDef="let element">
      <img
        class="status-icon"
        [src]="element.position | tdImgSrc"
        alt="up"
        [matTooltip]="element.position | tdMatTooltip"
      />
      {{element.position}}
    </td>

图像源管道

import { Pipe, PipeTransform } from "@angular/core";

@Pipe({
  name: "tdImgSrc"
})
export class TdImgSrcPipe implements PipeTransform {
  transform(statusId: number): string {
    switch (statusId % 3) {
      case 0:
        return `https://img-authors.flaticon.com/freepik.jpg`;
      case 1:
        return `https://www.flaticon.com/svg/vstatic/svg/68/68858.svg?token=exp=1616188223~hmac=6ef8123fc9aa7d33aaeddbe4dea787b6`;
      case 2:
        return `https://www.flaticon.com/svg/vstatic/svg/68/68792.svg?token=exp=1616188228~hmac=36273c59084428c6005d1f361cfb27f7`;
      // case 3:
      //   return `assets/svg/status-icon/open_icon.svg`;
      // case 4:
      //   return `assets/svg/status-icon/open_icon.svg`;
    }
  }
}

MatToolTip 管道

import { Pipe, PipeTransform } from "@angular/core";

@Pipe({
  name: "tdMatTooltip"
})
export class TdMatTooltipPipe implements PipeTransform {
  transform(statusId: number): string {
    switch (statusId % 5) {
      case 0:
        return "Open";
      case 1:
        return "Progress";
      case 2:
        return "Checked";
      case 3:
        return "Booked";
      case 4:
        return "Error";
    }
  }
}

这种分解的好处是您的代码将易于阅读和维护,因为每个管道都有一个单一的职责。

您可以在此处查看 stackblitz 上的代码 -> https://stackblitz.com/edit/angular-x9sdnn?file=app/table-basic-example.html

【讨论】:

    【解决方案2】:

    除非您真的知道自己在做什么,否则不惜一切代价避免使用 innerHTML,因为它很快就会导致 XSS 漏洞,即使您的直接字段不会导致可见的 XSS 漏洞。从简短的检查来看,几乎肯定有更好的方法来做到这一点,但如果没有实际的代码就很难知道。我建议执行以下操作:

    <td *matCellDef="let order" mat-cell>{someValue ? someValue : someOtherValue}</td>
    

    或者将其分离成一个函数。

    <td *matCellDef="let order" mat-cell>{MyComponent(order.statusForInterval)}</td>
    

    【讨论】:

      猜你喜欢
      • 2011-05-07
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      • 2019-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多