Предоставление пользовательского виджета в теневом домене веб-компонента для внешнего JS с использованием document.getElementsByClassName - PullRequest
0 голосов
/ 16 января 2020

У меня есть веб-компонент (сделан в angular) с теневым домом. Внутри этого компонента я могу иметь настраиваемый пользователем виджет. Как внешний JS может получить доступ к этому виджету, используя document.getElementsByClassName? Я просто хочу подчеркнуть, что если моя инкапсуляция представления веб-компонента имеет значение None, внешний JS может получить доступ к виджету. Вот пример веб-компонента, где я добавил для краткости жестко закодированный виджет. Если вы включите этот веб-компонент во внешнее приложение, то виджет внутри него не будет виден. Если вы установите ViewEncapsulation на None, вы увидите виджет. Однако мне нужно, чтобы инкапсуляция была ShadowDom и все еще иметь возможность доступа к виджету

import { Component, OnInit, ViewEncapsulation, ViewChild, AfterViewInit, Renderer2 } from '@angular/core';
import { ScriptLoaderService } from '../script-loader/script-loader.service';

@Component({
  selector: 'app-panel',
  template: `
    <slot>
      <p>
        My panel with custom widget
      </p>
      <div #parentDiv></div>
    </slot>
  `,
  styles: [],
  encapsulation: ViewEncapsulation.ShadowDom
})
export class PanelComponent implements OnInit, AfterViewInit {
  @ViewChild('parentDiv', { static: false }) parentDiv;

  constructor(
    private scriptLoader: ScriptLoaderService,
    public renderer: Renderer2
  ) { }

  ngOnInit() {
  }

  ngAfterViewInit(): void {
    this.scriptLoader.loadScript('https://weatherwidget.io/js/widget.min.js').then(() => {
      const element: HTMLElement = this.renderer.createElement('a');
      element.setAttribute('class', 'weatherwidget-io');
      element.setAttribute('href', 'https://forecast7.com/en/40d71n74d01/new-york/');
      element.setAttribute('data-label_1', 'NewYork');
      element.setAttribute('data-label_2', 'WHEATHER');
      element.setAttribute('data-theme', 'original');
      element.setAttribute('style', 'height:98px');
      this.renderer.appendChild(this.parentDiv.nativeElement, element);
    });
  }

}

Вот загрузчик скриптов

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})

export class ScriptLoaderService {
  private scripts: string[] = [];

  loadScript(scriptSource: string): Promise<any> {
    return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = scriptSource;
        script.onload = () => {
          resolve();
        };
        script.onerror = (error: any) => reject(error);
        document.getElementsByTagName('head')[0].appendChild(script);
      });
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...