使用路由器链接动态添加元素
Add element with RouterLink dynamically
当我在 Angular 组件中的某个地方放置一个锚元素时,如下所示:
<a [routerLink]="['/LoggedIn/Profile']">Static Link</a>
一切正常。单击链接时,Angular 路由器将导航到目标组件。
现在,我想动态添加相同的链接。在我的应用程序中的某个地方,我有一个"通知组件",它的唯一职责是显示通知。
通知组件执行以下操作:
<div [innerHTML]="notification.content"></div>
其中notification.content
是包含要显示的 HTML 的 NotificationComponent
类中的公共字符串变量。
notification.content
变量可以包含如下内容:
<div>Click on this <a [routerLink]="['/LoggedIn/Profile']">Dynamic Link</a> please</div>
一切正常并显示在我的屏幕上,但是当我单击动态链接时没有任何反应。
有没有办法让 Angular 路由器使用此动态添加的链接?
PS:我知道DynamicComponentLoader
,但我真的需要一个更不受限制的解决方案,我可以将各种HTML发送到我的通知组件,以及各种不同的链接。
在内容已经呈现后,无法添加 routerLink,但您仍然可以获得所需的结果:
-
创建一个包含动态数据的 href 并为其提供一个类:
`<a class="routerlink" href="${someDynamicUrl}">${someDynamicValue}</a>`
-
将 HostListener 添加到 app.component,该组件侦听单击并使用路由器导航
@HostListener('document:click', ['$event']) public handleClick(event: Event): void { if (event.target instanceof HTMLAnchorElement) { const element = event.target as HTMLAnchorElement; if (element.className === 'routerlink') { event.preventDefault(); const route = element?.getAttribute('href'); if (route) { this.router.navigate([`/${route}`]); } } }
}
routerLink
是一个指令。不会为使用 [innerHTML]
添加的 HTML 创建指令和组件。此 HTML 不是由 Angular 以任何方式处理的。
建议的方法是不使用[innerHTML]
而是使用DynamicComponentLoader ViewContainerRef.createComponent
,您将HTML包装在组件中并动态添加它。
有关示例,请参阅带有用户单击所选组件的 Angular 2 动态选项卡
从角度 9 开始,AOT 是编译角度项目的默认推荐方法。与 JIT 不同,AOT 在运行时不保存编译器的实例,这意味着您无法动态编译角度代码。可以在 angular 9 中禁用 AOT,但不建议这样做,因为您的捆绑包大小会更大,您的应用程序会变慢。
我解决这个问题的方法是在运行时使用渲染器 API 添加一个点击侦听器,防止 url 的默认行为并调用角度路由器
import { Directive, ElementRef, OnDestroy, OnInit, Renderer2 } from '@angular/core';
import { Router } from '@angular/router';
@Directive({
selector: '[hrefToRouterLink]'
})
export class HrefToRouterLinkDirective implements OnInit, OnDestroy {
private _listeners: { destroy: () => void }[] = [];
constructor(private _router: Router,
private _el: ElementRef,
private _renderer: Renderer2) {
}
ngOnInit() {
// TODO how to guarantee this directive running after all other directives without setTimeout?
setTimeout(() => {
const links = this._el.nativeElement.querySelectorAll('a');
links.forEach(link => {
this._renderer.setAttribute(link, 'routerLink', link?.getAttribute('href'));
const destroyListener = this._renderer.listen(link, 'click',
(_event) => {
_event.preventDefault();
_event.stopPropagation();
this._router.navigateByUrl(link?.getAttribute('href'));
});
this._listeners.push({ destroy: destroyListener });
});
}, 0);
}
ngOnDestroy(): void {
this._listeners?.forEach(listener => listener.destroy());
this._listeners = null;
}
}
你可以在这里找到一个例子: https://stackblitz.com/edit/angular-dynamic-routerlink-2
显然,上面解释的方法适用于JIT和AOT,但是如果您仍在使用JIT并希望动态编译组件(这可能有助于解决其他问题(。你可以在这里找到一个例子:https://stackblitz.com/edit/angular-dynamic-routerlink-1
使用的资源 :
https://stackoverflow.com/a/35082441/6209801
https://indepth.dev/here-is-what-you-need-to-know-about-dynamic-components-in-angular
结合其他一些答案 - 我希望它作为一个指令,这样我就可以针对正在 innerHTML'd 的特定元素,但为了避免使用 querySelector(等(来保持所有内容都是 Angulular。
我还发现了上述方法的一个问题,因为如果 href 是一个完整的 URL(即 https://www.example.com/abc(,将整个内容馈送到路由器将导致导航到/https。
我还需要检查以确保我们只路由器在我们的域内的 href。
@Directive({
selector: '[hrefToRouterLink]'
})
export class HrefToRouterLinkDirective {
constructor(private _router: Router){}
private _baseHref = quotemeta(environment.root_url.replace(`^https?://`, ''));
private _hrefRe: RegExp = new RegExp(`^(https?:)?(''/+)?(www''.)?${this._baseHref}`, `i`);
@HostListener('click', ['$event'])
onClick(e) {
// Is it a link?
if (!(e.target instanceof HTMLAnchorElement))
return;
let href: string = e.target?.getAttribute('href')
.replace(/(^'s+|'s+$)/gs, '');
// Is this a URL in our site?
if (!this._hrefRe.test(href))
return;
// If we're here, it's a link to our site, stop normal navigation
e.preventDefault();
e.stopPropagation();
// Feed the router.
this._router.navigateByUrl(
href.replace(this._hrefRe, '')
);
}
}
在上面的environment.root_url
描述了我们的基本域,quotemeta
是Perl-ish quotemeta函数的粗略实现,只是为了转义特殊字符。
YMMV 和我肯定错过了一些边缘情况,但这似乎工作正常。
- JQuery添加元素需要在我的js之前再次添加JQuery脚本
- 如何使用jquery遍历具有动态添加元素的数组
- jQuery appendTo 替换元素而不是添加元素,如果正在添加的元素预先存在于列表中
- 如何使用jquery添加元素
- 动态添加元素上的 HammerJS
- CSS没有'使用javascript向页面动态添加元素时无法工作
- 使用Javascript在DOM元素中添加元素
- 在添加元素时激发JS事件
- 什么's是在IE8+中添加元素的最有效方法
- d3.js在添加元素时协调
- 使用路由器链接动态添加元素
- 动态添加元素
- 在页面内容完全加载后,使用jQuery在DOM中添加元素
- j查询绑定单击不添加元素
- 在循环 jQuery 上添加元素
- 从一个页面调用 javascript 函数以在第二个页面上添加元素
- 页面加载后向<正文>添加元素时出现问题
- 动态添加元素时刷新 HTML
- 动态添加元素时不触发 JQuery 事件
- 如何使用 JavaScript 获取动态添加元素的宽度