Angular/Typescript 带有 routerLink 的文本
Angular/Typescript Text with routerLink
更新问题更清晰:
需要在 Angular HTML 中将一些文本和链接显示为内部 HTML(来自 service/DB 的数据),当用户点击时,它应该转到 Typescript 并以编程方式导航 router.navigate
此外,如何从 @ViewChild/ElementRef
添加 DomSanitizer
在下面的代码中添加了所有示例
Here is the updated stackblitz code
如截图所示 angular.io 一些文本和一些链接
你有一个 css 问题。
<a href="something"></a>
看起来像 link
<a [routerLink]="something"></a>
看起来像 link,因为如果你检查 HTML 它实际上会添加 href
属性 因为 routerLink
<a (click)="goTo()"></a>
看起来不像 link,因为没有 href
Chrome 和 Safari 默认用户代理 css 不会在没有 href
的情况下设置 <a>
样式(尚未确认 Firefox,但我确信它可能)。 bootstrap.
等框架也是如此
更新了 stackblitz CSS 移至全局,而不是 app.css
https://stackblitz.com/edit/angular-ivy-kkgmkc?embed=1&file=src/styles.css
这会将所有 link 样式设置为默认蓝色,或者 -webkit-link(如果该浏览器支持)。如果你想让它在整个应用程序中工作,它应该在你的 global.css 文件中。
a {
color: rgb(0, 0, 238);
color: -webkit-link;
cursor: pointer;
text-decoration: underline;
}
抱歉,我没有意识到你回答了我的评论。 Angular 路由不是次要的,如果您不使用 Angular 模块,您最终只会得到一个 HTML/CSS/Typescript 应用程序。你至少需要 Angular 的 RouterModule 才能使用路由,因此,用 DOM.
做它应该做的事情
第一个:
您没有导入 RouterModule
解决方案:
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot([]) // this one
]
第二个:
无法通过内部绑定Angular事件HTML 属性
修复:
利用 @ViewChild
指令更改 innerHTML
属性 并手动绑定到 click
事件,因此将 app.component.html
从
<div id="box" [innerHTML]="shouldbedivcontent" ></div>
至
<div #box id="box"></div>
现在,在您的 app.component.ts
中添加一个 属性 来保存对该“框”元素的引用,以便您稍后可以对 dom 与它:
@ViewChild('box') container: ElementRef;
实现 AfterViewInit,那个钩子是你可以实际处理你的容器的地方,如果你尝试在 OnInit 中使用它,你会得到未定义的,因为那个组件的 html 不在 dom还没有。
export class AppComponent implements AfterViewInit {
和
ngAfterViewInit() {
this.container.nativeElement.innerHTML = this.shouldbedivcontent;
this.container.nativeElement.addEventListener('click',
() => this.goto('bar')
);
}
更改 shouldbedivcontent
属性 来自:
'1) this is a click
<a (click)="goto("bar")">Click</a><br>
2)this is with routerlink
<a routerLink="" (click)="goto("bar")">Click</a><br>
3)This only works with href
<a href="goto/bar" title="bar">bar</a> and test'
至
'1) this is a click
<a id="link_1">Click</a><br>
2)this is with routerlink
<a [routerLink]="" (click)="goto(\'bar\')">Click</a><br>
3)This only works with href
<a href="goto/bar" title="bar">bar</a> and test'
即便如此,除非您自己应用一些样式,否则您仍然无法获得默认的锚点样式。
第三
您没有HTML消毒,这可能很危险。 read more here
我的建议:
对于您来说似乎有很多事情要做,对于与您一起工作的其他人来说似乎有很多事情要阅读,而您可以像下面的示例一样轻松地做到这一点!
将您的 html 移动到您的 app.component.html
:
<div id="box">
1) this is a click
<a (click)="goto('bar')">Click</a><br>
2)this is with routerlink
<a routerLink="" (click)="goto('bar')">Click</a><br>
3)This only works with href
<a href="goto/bar" title="bar">bar</a> and test
</div>
<p>Below is actual content</p>
你会注意到现在一切正常,除了没有 routerLink 或 href 的锚点,因为那不是 link。
编辑:
看看新的 stackblitz,我建议改变方法,绑定到 innerHTML 在处理纯文本甚至一些简单的 html 时是可以的,但不是绑定事件的好选择或路由逻辑。
Angular 的 Renderer2 提供了一组动态添加元素到 DOM 的方法。有了 table,你只需要一点点努力就可以把你从后端得到的那个简单的 html 变成类似的东西(将这个 属性 粘贴到你的代码中来测试它以及下面提供的其余代码):
public jsonHTML = [
{
tagName: '',
text: 'some text with click ',
attributes: {
}
},
{
tagName: 'a',
text: 'bar',
attributes: {
value: 'bar' // goto parameter
}
},
{
tagName: '',
text: ' some more text with click ',
attributes: {
}
},
{
tagName: 'a',
text: 'foo',
attributes: {
value: 'foo' // goto parameter
}
}
]
有了它之后,动态创建所有这些元素就容易多了:
这是您 Q1 中的代码:
用 private r2: Renderer2
注入 Renderer2
并将AfterViewInit hook中的Q1相关代码替换为:
const parent = this.r2.createElement('div'); // container div to our stuff
this.jsonHTML.forEach((element) => {
const attributes = Object.keys(element.attributes);
const el = element.tagName && this.r2.createElement(element.tagName);
const text = this.r2.createText(element.text);
if (!el) { // when there's no tag to create we just create text directly into the div.
this.r2.appendChild(
parent,
text
);
} else { // otherwise we create it inside <a></a>
this.r2.appendChild(
el,
text
);
this.r2.appendChild(
parent,
el
);
}
if (attributes.length > 0) {
attributes.forEach((name) => {
if (el) {
this.r2.setAttribute(el, name, element.attributes[name]); // just the value attribute for now
if (name === 'value') {
this.r2.listen(el, 'click', () => {
this.goto(element.attributes[name]); // event binding with property "value" as parameter to navigate to
})
}
} else {
throw new Error('no html tag specified as element...');
}
})
}
})
this.r2.appendChild(this.container.nativeElement, parent); // div added to the DOM
不需要 html 消毒剂,也不需要使用 routerLink,只需注入 Router 并导航到您想要的路线!对代码进行改进使其满足您的需求,它至少应该是一个好的起点
祝你好运!
这非常适合我 :D
@Directive({
selector: "[linkify]",
})
// * Apply Angular Routing behavior, PreventDefault behavior
export class CustomLinkDirective {
@Input()
appStyle: boolean = true;
constructor(
private router: Router,
private ref: ElementRef,
@Inject(PLATFORM_ID) private platformId: Object
) {}
@HostListener("click", ["$event"])
onClick(e: any) {
e.preventDefault();
const href = e.target.getAttribute("href");
href && this.router.navigate([href]);
}
ngAfterViewInit() {
if (isPlatformBrowser(this.platformId)) {
this.ref.nativeElement.querySelectorAll("a").forEach((a: HTMLElement) => {
const href = a.getAttribute("href");
href &&
this.appStyle &&
a.classList.add("text-indigo-600", "hover:text-indigo-500");
});
}
}
}
我如何使用它
<p linkify
class="mt-3 text-lg text-gray-500 include-link"
[innerHtml]="apiSectionText"
></p>
result
更新问题更清晰:
需要在 Angular HTML 中将一些文本和链接显示为内部 HTML(来自 service/DB 的数据),当用户点击时,它应该转到 Typescript 并以编程方式导航 router.navigate
此外,如何从 @ViewChild/ElementRef
添加 DomSanitizer在下面的代码中添加了所有示例
Here is the updated stackblitz code
如截图所示 angular.io 一些文本和一些链接
你有一个 css 问题。
<a href="something"></a>
看起来像 link<a [routerLink]="something"></a>
看起来像 link,因为如果你检查 HTML 它实际上会添加href
属性 因为routerLink
<a (click)="goTo()"></a>
看起来不像 link,因为没有href
Chrome 和 Safari 默认用户代理 css 不会在没有 href
的情况下设置 <a>
样式(尚未确认 Firefox,但我确信它可能)。 bootstrap.
更新了 stackblitz CSS 移至全局,而不是 app.css https://stackblitz.com/edit/angular-ivy-kkgmkc?embed=1&file=src/styles.css
这会将所有 link 样式设置为默认蓝色,或者 -webkit-link(如果该浏览器支持)。如果你想让它在整个应用程序中工作,它应该在你的 global.css 文件中。
a {
color: rgb(0, 0, 238);
color: -webkit-link;
cursor: pointer;
text-decoration: underline;
}
抱歉,我没有意识到你回答了我的评论。 Angular 路由不是次要的,如果您不使用 Angular 模块,您最终只会得到一个 HTML/CSS/Typescript 应用程序。你至少需要 Angular 的 RouterModule 才能使用路由,因此,用 DOM.
做它应该做的事情第一个:
您没有导入 RouterModule
解决方案:
imports: [ BrowserModule, FormsModule, RouterModule.forRoot([]) // this one ]
第二个:
无法通过内部绑定Angular事件HTML 属性
修复:
利用 @ViewChild
指令更改 innerHTML
属性 并手动绑定到 click
事件,因此将 app.component.html
从
<div id="box" [innerHTML]="shouldbedivcontent" ></div>
至
<div #box id="box"></div>
现在,在您的 app.component.ts
中添加一个 属性 来保存对该“框”元素的引用,以便您稍后可以对 dom 与它:
@ViewChild('box') container: ElementRef;
实现 AfterViewInit,那个钩子是你可以实际处理你的容器的地方,如果你尝试在 OnInit 中使用它,你会得到未定义的,因为那个组件的 html 不在 dom还没有。
export class AppComponent implements AfterViewInit {
和
ngAfterViewInit() {
this.container.nativeElement.innerHTML = this.shouldbedivcontent;
this.container.nativeElement.addEventListener('click',
() => this.goto('bar')
);
}
更改 shouldbedivcontent
属性 来自:
'1) this is a click
<a (click)="goto("bar")">Click</a><br>
2)this is with routerlink
<a routerLink="" (click)="goto("bar")">Click</a><br>
3)This only works with href
<a href="goto/bar" title="bar">bar</a> and test'
至
'1) this is a click
<a id="link_1">Click</a><br>
2)this is with routerlink
<a [routerLink]="" (click)="goto(\'bar\')">Click</a><br>
3)This only works with href
<a href="goto/bar" title="bar">bar</a> and test'
即便如此,除非您自己应用一些样式,否则您仍然无法获得默认的锚点样式。
第三
您没有HTML消毒,这可能很危险。 read more here
我的建议:
对于您来说似乎有很多事情要做,对于与您一起工作的其他人来说似乎有很多事情要阅读,而您可以像下面的示例一样轻松地做到这一点!
将您的 html 移动到您的 app.component.html
:
<div id="box">
1) this is a click
<a (click)="goto('bar')">Click</a><br>
2)this is with routerlink
<a routerLink="" (click)="goto('bar')">Click</a><br>
3)This only works with href
<a href="goto/bar" title="bar">bar</a> and test
</div>
<p>Below is actual content</p>
你会注意到现在一切正常,除了没有 routerLink 或 href 的锚点,因为那不是 link。
编辑:
看看新的 stackblitz,我建议改变方法,绑定到 innerHTML 在处理纯文本甚至一些简单的 html 时是可以的,但不是绑定事件的好选择或路由逻辑。
Angular 的 Renderer2 提供了一组动态添加元素到 DOM 的方法。有了 table,你只需要一点点努力就可以把你从后端得到的那个简单的 html 变成类似的东西(将这个 属性 粘贴到你的代码中来测试它以及下面提供的其余代码):
public jsonHTML = [
{
tagName: '',
text: 'some text with click ',
attributes: {
}
},
{
tagName: 'a',
text: 'bar',
attributes: {
value: 'bar' // goto parameter
}
},
{
tagName: '',
text: ' some more text with click ',
attributes: {
}
},
{
tagName: 'a',
text: 'foo',
attributes: {
value: 'foo' // goto parameter
}
}
]
有了它之后,动态创建所有这些元素就容易多了:
这是您 Q1 中的代码:
用 private r2: Renderer2
并将AfterViewInit hook中的Q1相关代码替换为:
const parent = this.r2.createElement('div'); // container div to our stuff
this.jsonHTML.forEach((element) => {
const attributes = Object.keys(element.attributes);
const el = element.tagName && this.r2.createElement(element.tagName);
const text = this.r2.createText(element.text);
if (!el) { // when there's no tag to create we just create text directly into the div.
this.r2.appendChild(
parent,
text
);
} else { // otherwise we create it inside <a></a>
this.r2.appendChild(
el,
text
);
this.r2.appendChild(
parent,
el
);
}
if (attributes.length > 0) {
attributes.forEach((name) => {
if (el) {
this.r2.setAttribute(el, name, element.attributes[name]); // just the value attribute for now
if (name === 'value') {
this.r2.listen(el, 'click', () => {
this.goto(element.attributes[name]); // event binding with property "value" as parameter to navigate to
})
}
} else {
throw new Error('no html tag specified as element...');
}
})
}
})
this.r2.appendChild(this.container.nativeElement, parent); // div added to the DOM
不需要 html 消毒剂,也不需要使用 routerLink,只需注入 Router 并导航到您想要的路线!对代码进行改进使其满足您的需求,它至少应该是一个好的起点
祝你好运!
这非常适合我 :D
@Directive({
selector: "[linkify]",
})
// * Apply Angular Routing behavior, PreventDefault behavior
export class CustomLinkDirective {
@Input()
appStyle: boolean = true;
constructor(
private router: Router,
private ref: ElementRef,
@Inject(PLATFORM_ID) private platformId: Object
) {}
@HostListener("click", ["$event"])
onClick(e: any) {
e.preventDefault();
const href = e.target.getAttribute("href");
href && this.router.navigate([href]);
}
ngAfterViewInit() {
if (isPlatformBrowser(this.platformId)) {
this.ref.nativeElement.querySelectorAll("a").forEach((a: HTMLElement) => {
const href = a.getAttribute("href");
href &&
this.appStyle &&
a.classList.add("text-indigo-600", "hover:text-indigo-500");
});
}
}
}
我如何使用它
<p linkify
class="mt-3 text-lg text-gray-500 include-link"
[innerHtml]="apiSectionText"
></p>
result