Javascript 使用RouterLink动态添加元素
当我把一个锚元素放在一个角度分量的某个地方,像这样:Javascript 使用RouterLink动态添加元素,javascript,typescript,angular,angular2-routing,Javascript,Typescript,Angular,Angular2 Routing,当我把一个锚元素放在一个角度分量的某个地方,像这样: 静态链接 一切正常。单击链接时,角度路由器将导航到目标组件 现在,我想动态添加相同的链接。在我的应用程序中,我有一个“通知组件”,它的唯一职责就是显示通知 通知组件执行如下操作: 其中,notification.content是NotificationComponent类中的一个公共字符串变量,它包含要显示的HTML notification.content变量可以包含以下内容: 请点击这个动态链接 一切正常,并显示在我的屏幕上,但当
静态链接
一切正常。单击链接时,角度路由器将导航到目标组件
现在,我想动态添加相同的链接。在我的应用程序中,我有一个“通知组件”,它的唯一职责就是显示通知
通知组件执行如下操作:
其中,notification.content
是NotificationComponent
类中的一个公共字符串变量,它包含要显示的HTML
notification.content
变量可以包含以下内容:
请点击这个动态链接
一切正常,并显示在我的屏幕上,但当我点击动态链接时,什么也没有发生
有没有办法让角度路由器与这个动态添加的链接一起工作
PS:我知道DynamicComponentLoader,但我真的需要一个更不受限制的解决方案,我可以通过各种不同的链接将各种HTML发送到通知组件。
routerLink
是一个指令。不会为使用[innerHTML]
添加的HTML创建指令和组件。此HTML不以任何方式由Angular处理
建议不要使用[innerHTML]
而是使用ViewContainerRef.createComponent
将HTML包装到组件中并动态添加
有关示例,请参见在内容已呈现后无法添加routerLink,但您仍然可以获得所需的结果:
`<a class="routerlink" href="${someDynamicUrl}">${someDynamicValue}</a>`
}
自angular 9以来,AOT是编译angular项目的默认推荐方式。 与JIT不同,AOT在运行时不保存编译器的实例,这意味着您无法动态编译角度代码。 可以在angular 9中禁用AOT,但不建议这样做,因为您的包大小会更大,应用程序会更慢 我解决这个问题的方法是在运行时使用渲染器api添加一个单击侦听器,防止URL的默认行为并调用angular router
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;
}
}
您可以在此处找到一个示例:
显然,上面解释的方法对JIT和AOT都有效,但如果您仍然使用JIT并希望动态编译组件(这可能有助于解决其他问题)。您可以在此处找到一个示例:
使用的资源:
嗯,这不是我所希望的答案。我真的不想为每个不同的通知创建一个组件。我希望有一种方法可以让angular扫描dom以查找任何新添加的指令或其他内容……您可以将数据传递到组件,并在组件模板中绑定到该组件,以使其可用于类似场景。如果HTML是由用户提供的,并且在构建时无法知道,则此限制通常是一个问题。动态添加的组件可以由其他组件提供,它们不需要在
指令中列出:[……]
Thank:)请参阅此类包装的示例。@GünterZöchbauer感谢您的回答,但您提供的链接不起作用。嘿,您找到解决方案了吗?就是这个!你的答案应该是公认的答案!非常感谢你!非常感谢。这是一个非常好的解决方法。如果动态url中有,可以使用router.navigateByUrl()
。
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;
}
}