(щелчок) функция не работает в SVG при маршрутизации из файла TS - PullRequest
0 голосов
/ 12 января 2019

У меня есть веб-страница, которая использует Angular и маршрутизирует данные из файла TS. Все работает, кроме (нажмите).

Если я помещаю SVG с функцией (click) непосредственно в HTML, это работает, но если я вызываю SVG из файла TS, это не так. Если я удаляю (щелкните) = 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);
  }
}

проект-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), ссылка также не открывалась на мобильном устройстве, хотя linkOpen () работал / работает, как и ожидалось, при использовании инспектора Chrome для предварительного просмотра в качестве устройства.

Ответы [ 3 ]

0 голосов
/ 15 января 2019

Поместив событие click в div, который вызывает innerHTML, и оставив целевой элемент в SVG a, все получилось, ни один из слушателей не понадобился.

Чтобы решить проблему с мобильными устройствами, я продублировал SVG, использовал машинописный текст для вызова только на мобильных устройствах и добавил «xlink:» в href, потому что iOS требует этого. Xlink ограничен, но больше ничего не работает.

0 голосов
/ 16 января 2019

Мое понимание проблемы заключается в том, что вам нужно добавить eventListener для щелчка мышью на #imgLink. Но вы не можете сделать это, пока он не существует, вам нужно, чтобы элемент был в DOM, чтобы добавить событие. Afaik, подход (щелчок) не сработает по причинам, указанным Сэмом.

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

Это показывает концептуально, как вы можете сделать это. Проблема заключается в том, что он включает в себя внутренний setTimeout, и это не так красиво. Так что проблема в основном только в сроках.

Одним из способов достижения этого является директива, устанавливающая событие click в ngAfterViewInit (https://angular.io/guide/lifecycle-hooks). Возможно, потребуется также вывод (https://angular.io/guide/component-interaction#parent-listens-for-child-event).) Другой альтернативой является полноценный компонент, шаблон которого это svg из project-details.ts. Затем вы можете захватить событие клика «обычно».

Некоторые другие предложения:

  • Перемещение ссылки за пределы svg на родительский элемент (не уверен, будет ли это работать для вашего варианта использования)
  • Перемещение project-detais в файл .svg и использование тега img.

Почему это не могло работать на мобильных устройствах: кто знает, что мобильное устройство странно (это происходит от того, чья работа на полный рабочий день разрабатывается для мобильных устройств с angular). А если серьезно, вот некоторые ссылки, которые могут помочь https://developer.mozilla.org/en-US/docs/Web/API/Touch_events/Supporting_both_TouchEvent_and_MouseEvent, https://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 объясняет лучше, чем я могу.

0 голосов
/ 12 января 2019

Я думаю, что этот HTML связывается до того, как этот динамический HTML добавляется. Попробуйте добавить слушатель в свой компонентный контроллер (project.component.ts)

Вот ссылка для этого:

Динамически добавить прослушиватель событий

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...