为特定关键字在文本中动态添加 matTooltip
Dynamically add matTooltip in text for specific keywords
我在个人 Angular 项目中工作(使用 Angular Material),但找不到解决此问题的方法。
例如,我有一个像这样的长文本:
When you take the Dodge action, you focus entirely on avoiding
attacks. Until the start of your next turn, any Attack roll made
against you has disadvantage if you can see the attacker, and you make
Dexterity Saving Throws with advantage. You lose this benefit if you
are Incapacitated (as explained in Conditions ) or if your speed drops
to 0.
我有一些关键字,这里是缺点,优点是无能为力。我想将字体设为粗体并添加一个工具提示,为每个关键字添加一个小的解释。
我可以用管道将字体加粗,但我找不到为关键字添加工具提示的解决方案。使用 innerHTML 不起作用,这是我目前的解决方案:
<div innerHTML="description | transformKeyWord"></div>
还有我的烟斗:
transform(value: string, ...args: unknown[]): unknown {
let result = value
result = result.replace('advantage', '<span matTooltip="Advantage description">advantage</span>')
result = result.replace('incapacitated', '<b [matTooltip]="Incapacitated description">incapacitated</b>')
return result;
}
我不认为这是使用带有 innerHTML 的管道的好解决方案,这就是我寻求帮助的原因。
TLDR: https://stackblitz.com/edit/angular-ivy-86uxvs?file=src/app/app.component.html
在我看来,每个关键字都是一个 object
加上一个 word
和一个 tooltip
。因此,我将为此定义架构。
export type keyword = {
word: string;
tooltip: string;
};
我将在对象中定义关键字以便于查找:
keywords: { [key: string]: keyword } = {
disadvantage: {
word: 'disadvantage',
tooltip: 'advantage description',
},
incapacitated: {
word: 'incapacitated',
tooltip: 'incapacitated description',
},
};
我觉得最好的办法就是把字符串拆分成字符串和关键字的数组,这样我们就可以按顺序打印到html了。这是一个执行此操作的函数 - 我将所有这些都放在一个服务中,因为它看起来很合适。
toDynamicText(text: string): (string | keyword)[] {
const res: (string | keyword)[] = [];
const tokens = text.split(' ');
let i = 0;
for (const token of tokens) {
let keyword = this.keywords[token.toLowerCase()]; //undefined if word is not a keyword
if (keyword) {
i = res.push(keyword);
} else {
if (!res[i]) res[i] = token;
else res[i] += ' ' + token;
}
}
return res;
}
输出数组如下所示:
[
"When you take the Dodge action, you focus entirely on avoiding attacks. Until the start of your next turn, any Attack roll made against you has",
{
"word": "disadvantage",
"tooltip": "advantage description"
},
"if you can see the attacker, and you make Dexterity Saving Throws with advantage. You lose this benefit if you are",
{
"word": "incapacitated",
"tooltip": "incapacitated description"
},
"(as explained in Conditions ) or if your speed drops to 0. "
]
这是一个如何使用它的例子:
text =
'When you take the Dodge action, you focus entirely on avoiding attacks. ' +
'Until the start of your next turn, any Attack roll made against you has disadvantage if you can see the attacker, ' +
'and you make Dexterity Saving Throws with advantage. ' +
'You lose this benefit if you are Incapacitated (as explained in Conditions ) or if your speed drops to 0. ';
dynamicText: (string | keyword)[] = [];
constructor(private dynamicTextService: DynamicTextService) {}
ngOnInit(): void {
this.dynamicText = this.dynamicTextService.toDynamicText(this.text);
}
isString(token: any) {
return typeof token === 'string';
}
//Typescript compiler wants a typecast, so we have two helper functions
getTooltip(token: string | keyword) {
return (token as keyword).tooltip;
}
getWord(token: string | keyword) {
return (token as keyword).word;
}
<p>
<ng-container *ngFor="let token of dynamicText">
<ng-container *ngIf="isString(token)">{{ token }}</ng-container>
<ng-container *ngIf="!isString(token)"
><b [matTooltip]="getTooltip(token)" style="cursor: pointer">
{{ getWord(token) }}
</b></ng-container
>
</ng-container>
</p>
您可以通过在尝试 return 之前确保 tooltip
和 word
属性存在来使其更健壮。
我会将其作为输入变量 text
的组件。
我在个人 Angular 项目中工作(使用 Angular Material),但找不到解决此问题的方法。
例如,我有一个像这样的长文本:
When you take the Dodge action, you focus entirely on avoiding attacks. Until the start of your next turn, any Attack roll made against you has disadvantage if you can see the attacker, and you make Dexterity Saving Throws with advantage. You lose this benefit if you are Incapacitated (as explained in Conditions ) or if your speed drops to 0.
我有一些关键字,这里是缺点,优点是无能为力。我想将字体设为粗体并添加一个工具提示,为每个关键字添加一个小的解释。
我可以用管道将字体加粗,但我找不到为关键字添加工具提示的解决方案。使用 innerHTML 不起作用,这是我目前的解决方案:
<div innerHTML="description | transformKeyWord"></div>
还有我的烟斗:
transform(value: string, ...args: unknown[]): unknown {
let result = value
result = result.replace('advantage', '<span matTooltip="Advantage description">advantage</span>')
result = result.replace('incapacitated', '<b [matTooltip]="Incapacitated description">incapacitated</b>')
return result;
}
我不认为这是使用带有 innerHTML 的管道的好解决方案,这就是我寻求帮助的原因。
TLDR: https://stackblitz.com/edit/angular-ivy-86uxvs?file=src/app/app.component.html
在我看来,每个关键字都是一个 object
加上一个 word
和一个 tooltip
。因此,我将为此定义架构。
export type keyword = {
word: string;
tooltip: string;
};
我将在对象中定义关键字以便于查找:
keywords: { [key: string]: keyword } = {
disadvantage: {
word: 'disadvantage',
tooltip: 'advantage description',
},
incapacitated: {
word: 'incapacitated',
tooltip: 'incapacitated description',
},
};
我觉得最好的办法就是把字符串拆分成字符串和关键字的数组,这样我们就可以按顺序打印到html了。这是一个执行此操作的函数 - 我将所有这些都放在一个服务中,因为它看起来很合适。
toDynamicText(text: string): (string | keyword)[] {
const res: (string | keyword)[] = [];
const tokens = text.split(' ');
let i = 0;
for (const token of tokens) {
let keyword = this.keywords[token.toLowerCase()]; //undefined if word is not a keyword
if (keyword) {
i = res.push(keyword);
} else {
if (!res[i]) res[i] = token;
else res[i] += ' ' + token;
}
}
return res;
}
输出数组如下所示:
[
"When you take the Dodge action, you focus entirely on avoiding attacks. Until the start of your next turn, any Attack roll made against you has",
{
"word": "disadvantage",
"tooltip": "advantage description"
},
"if you can see the attacker, and you make Dexterity Saving Throws with advantage. You lose this benefit if you are",
{
"word": "incapacitated",
"tooltip": "incapacitated description"
},
"(as explained in Conditions ) or if your speed drops to 0. "
]
这是一个如何使用它的例子:
text =
'When you take the Dodge action, you focus entirely on avoiding attacks. ' +
'Until the start of your next turn, any Attack roll made against you has disadvantage if you can see the attacker, ' +
'and you make Dexterity Saving Throws with advantage. ' +
'You lose this benefit if you are Incapacitated (as explained in Conditions ) or if your speed drops to 0. ';
dynamicText: (string | keyword)[] = [];
constructor(private dynamicTextService: DynamicTextService) {}
ngOnInit(): void {
this.dynamicText = this.dynamicTextService.toDynamicText(this.text);
}
isString(token: any) {
return typeof token === 'string';
}
//Typescript compiler wants a typecast, so we have two helper functions
getTooltip(token: string | keyword) {
return (token as keyword).tooltip;
}
getWord(token: string | keyword) {
return (token as keyword).word;
}
<p>
<ng-container *ngFor="let token of dynamicText">
<ng-container *ngIf="isString(token)">{{ token }}</ng-container>
<ng-container *ngIf="!isString(token)"
><b [matTooltip]="getTooltip(token)" style="cursor: pointer">
{{ getWord(token) }}
</b></ng-container
>
</ng-container>
</p>
您可以通过在尝试 return 之前确保 tooltip
和 word
属性存在来使其更健壮。
我会将其作为输入变量 text
的组件。