从TS文件路由时,(单击)功能在SVG中不起作用

时间:2019-01-11 21:38:40

标签: angular typescript svg

我有一个使用Angular并从TS文件路由数据的网页。一切正常,除了(单击)。

如果我将带有(click)函数的SVG直接放在HTML中,则可以使用,但是,如果我从TS文件中调用SVG,则不可以。如果删除(click)= linkOpen(),则该链接会继续在新窗口中打开;如果我删除target = iframe,则该链接会在当前标签中打开。

project.component.html:

    <div class="page" *ngIf="project$ | async as project">
        <div [innerHTML]="svgHTML(project)"></div>
    </div>

project.component.ts:

import { Component, OnInit, Injectable } from '@angular/core';
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
import { switchMap } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { DomSanitizer } from '@angular/platform-browser';

import { CopeAdditionsService } from '../cope-additions.service';
import { Project } from '../project';

@Component({
  selector: 'app-project',
  templateUrl: './project.component.html',
  styleUrls: ['./project.component.css']
})

@Injectable()
export class ProjectComponent implements OnInit {
  display: boolean;
  project$: Observable<Project>;

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private service: CopeAdditionsService,
    public sanitizer: DomSanitizer
  ) {
    this.display = false;
  }

  ngOnInit() {
    this.project$ = this.route.paramMap.pipe(
      switchMap((params: ParamMap) =>
        this.service.getProject(params.get('id')))
    );
  }

  gotoProjects(project: Project) {
    let projectId = project ? project.id : null;
    this.router.navigate(['/cope-additions', { id: projectId }]);
  }

  linkOpen() {
    if (window.innerWidth >= 600) {
      this.display = true;
      document.getElementById('imgLink').setAttribute('target', 'iframe');
    } else {
      this.display = false;
      document.getElementById('imgLink').setAttribute('target', '_self');
    }
  }

  svgHTML(project) {
    return this. sanitizer.bypassSecurityTrustHtml(project.SVG);
  }
}

project-details.ts:

    SVG:`
        <svg class=\'svg\' fill=\'transparent\' id=\'svg5\' xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 476 612\'>
            <a href=\'/cope-additions/5/lot/15\' id=\'imgLink\' target=\'iframe\' (click)=\'linkOpen()\'><rect class=\'lot-for-sale\' x=\'64\' y=\'40\' width=\'125.5\' height=\'95\' alt=\'B-1\'><title>lot for sale</title></rect></a>
        </svg>`

该链接不是在iframe中打开,而是在一个新标签页中打开,但在移动设备上则完全不会打开。在将SVG移到TS文件(直接在HTML文件中)之前,该链接也没有在移动设备上打开,尽管在使用Chrome检查器作为设备进行预览时linkOpen()可以按预期工作/工作。

3 个答案:

答案 0 :(得分:2)

我对问题的理解是,您需要为#imgLink添加一个click的事件监听器。但是,直到它存在,您才能做到这一点,您需要将元素包含在DOM中以添加事件。 Afaik,(点击)方法由于Sam所说的原因而行不通。

https://stackblitz.com/edit/angular-bhbwkd

从概念上显示了如何执行此操作。问题在于它涉及内部setTimeout,而且还不够漂亮。所以问题基本上只是时间。

一种方法是使用指令,在ngAfterViewInit(https://angular.io/guide/lifecycle-hooks)中设置click事件。它可能还需要一个输出(https://angular.io/guide/component-interaction#parent-listens-for-child-event)。另一种选择是使用完整组件,其模板是project-details.ts中的svg。然后,您可以“正常”捕获点击事件。

其他一些建议:

  • 将svg外部的链接移动到父元素(不确定是否适用于您的用例)
  • 将project-detais移至.svg文件并使用img标签。

为什么它可能不适用于移动设备:谁知道移动设备很奇怪(这是因为他的专职工作是为带角度的移动设备开发的人)。但是,严重的是,有些链接可能对https://developer.mozilla.org/en-US/docs/Web/API/Touch_events/Supporting_both_TouchEvent_and_MouseEventhttps://developer.mozilla.org/en-US/docs/Web/API/Touch_events/Using_Touch_Events有帮助。通常,如果您获得触摸事件,那么您也应该获得点击事件。 SVG可能是魔术。我建议尝试捕获所有的触摸/单击事件,以查看正在运行的事件及其顺序,然后尝试找出原因。如果您打算做任何复杂的事情,而需要良好的移动支持http://hammerjs.github.io/就是一个很好的解决方案。

尾注:如果手动添加点击事件,则我建议使用Renderer2而不是直接进行操作https://medium.com/@kmathy/angular-manipulate-properly-the-dom-with-renderer-16a756508cba,这比我可以解释的更好。

答案 1 :(得分:1)

我认为在添加动态HTML之前先绑定HTML。尝试在组件控制器(project.component.ts)中添加侦听器

这是该链接:

Dynamically add event listener

答案 2 :(得分:0)

把click事件放在调用innerHTML的div上,并将目标留在SVG上的一个元素上就可以了,不需要任何侦听器。

为解决移动问题,我复制了SVG,使用打字稿仅在移动设备上调用它,并在href中添加了“ xlink:”,因为iOS要求这么做。 Xlink已废弃,但似乎没有其他作用。