按照注释中的建议,我制定了一个指令,解析输入并根据输入将DOM元素添加到修饰元素中,括号中的术语输出跨度,onclick处理程序触发角度导航。以下是一个早期可行的解决方案:
import { Directive, ElementRef, Input, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { MaterialColor } from '../libraries/material-color.enum';
import { Logger } from '../shared/utility/logger';
/**
* An Angular directive that takes in a string of content and parses out terms inside of brackets, treating them as links to new topics.
*/
@Directive({
selector: '[emHelpLink]'
})
export class HelpLinkDirective implements OnInit {
@Input('emHelpLink') public helpContent: string = '';
constructor(private el: ElementRef, private router: Router) {
Logger.debug(`Help link directive: ${this.helpContent}`, el);
}
/**
* Responds to the Angular onInit event. It's important to look at helpContent here as it may not be set during construction.
*/
public ngOnInit(): void {
this.parseText(this.helpContent);
}
/**
* Parses the input text and adds spans to the native element this directive decorates, replacing bracketed terms with router links.
* @param {string} input the text to translate
*/
private parseText(input: string): void {
if (!input) {
return;
}
// Declare loop variables
let remaining: string = input;
let startIndex: number = remaining.indexOf('[');
let endIndex: number = remaining.indexOf(']');
/* We're going to loop through and find the first bracketed set of terms, then transform those to links. Items before this will be treated
as spans, and items afterwards will be re-evaluated for bracketed terms. If no remaining brackets are detected (or no brackets are present)
the remaining text will be output as a span.
*/
do {
startIndex = remaining.indexOf('[');
endIndex = remaining.indexOf(']');
if (startIndex >= 0 && endIndex > startIndex) {
this.addSpanText(remaining.slice(0, startIndex));
const substring: string = remaining.slice(startIndex + 1, endIndex);
this.addHelpLink(substring);
remaining = remaining.slice(endIndex + 1);
}
} while (startIndex >= 0 && endIndex > startIndex);
if (remaining) {
this.addSpanText(remaining);
}
}
/**
* Adds a span tag to the document with the specified text
* @param {string} text the text to include in the span.
*/
private addSpanText(text: string): void {
if (!text) {
return;
}
const span: HTMLSpanElement = document.createElement('span');
span.innerText = text;
this.el.nativeElement.appendChild(span);
}
/**
* Builds a span tag for the given help text that will navigate to the help topic when clicked. This will be a span tag
* styled as an anchor tag.
* @param {string} text the text to display in the link.
*/
private addHelpLink(text: string): void {
if (!text) {
return;
}
const link: HTMLElement = document.createElement('span');
link.style.cursor = 'pointer';
link.style.color = MaterialColor.blue;
link.title = `View help on '${text}'`;
link.innerText = text;
link.onclick = (): void => this.onLinkClick(text);
this.el.nativeElement.appendChild(link);
}
/**
* Responds to a help topic link click event by triggering an Angular routing event.
* @param {string} text the help topic clicked.
*/
private onLinkClick(text: string): void {
Logger.debug(`Help topic clicked ${text}`);
if (!text) {
return;
}
this.router.navigate(['/help', 'topic', text]);
}
}