Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/416.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用RouterLink动态添加元素_Javascript_Typescript_Angular_Angular2 Routing - Fatal编程技术网

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,但您仍然可以获得所需的结果:

  • 使用动态数据创建href,并为其设置一个类:

    `<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;
      }
    
    }