Тег script в angular2 шаблон / ловушка при загрузке шаблона dom

Я застрял и не знаю, как решить мою проблему...

Упрощенно: у меня есть компонент, который создает ulist на основе привязки, например:

@Component({
   selector: "template",
   template: `
     <ul>
       <li *ng-for="#challenge of jobs.challenges">{{challenge}}</li>
     </ul>
   `})
export class JobTemplate{
  jobs: Jobs;
  constructor(jobs:Jobs){
    this.jobs = jobs
  }     
}

Селектор / хост компонента встроен в обычный поток HTML, повторяемый php, и используется для замены предопределенного ulist. Проблема в том, что на обычном сайте, тег script после ulist использовался для применения некоторой магии jquery к списку.

Поскольку тег script выводится до завершения загрузки шаблона моего компонента, вызовы jquery не найдут элементы DOM моего шаблона. Помещение тега script внутри моего шаблона (в конце) не работает; это, кажется, просто игнорируется.

<ul>
  <a><li *ng-for="#challenge of jobs.challenges">{{challenge}}</li></a>  
</ul>
<script>
   $("ul a").on("click", function (event)
        {
        var parent = $(this).parent();
        if(parent.hasClass('active'))
          ....slideToggle("normal");
        else
        ....
        });
</script>

Кроме того, сайт использует базовую структуру, и каждый раз, когда на страницу добавляется новый элемент (например, посредством привязки моего компонента, обновляемого извне), мне нужно позвонить $(document).foundation(),

Поэтому мой вопрос заключается в том, как мне добиться вызова jquery для моего шаблона DOM, когда я не знаю, закончил ли мой шаблон создания. Обработчик onload также не работает, когда он определен в моем шаблоне компонента.

Я читал о AfterViewInit, но я немного ошеломлен этим. Может кто-нибудь, пожалуйста, подтолкнуть меня в правильном направлении?

Как я могу узнать, когда шаблон моего компонента был полностью вставлен в "основной" DOM?

2 ответа

Теги скриптов в шаблонах компонентов удалены. Обходной путь - динамически создать тег сценария в ngAfterViewInit()

Смотрите также https://github.com/angular/angular/issues/4903

constructor(private elementRef:ElementRef) {};

ngAfterViewInit() {
  var s = document.createElement("script");
  s.type = "text/javascript";
  s.src = "http://somedomain.com/somescript";
  this.elementRef.nativeElement.appendChild(s);
}

Смотрите также /questions/17532094/kak-dobavit-script-script-v-javascript/17532107#17532107

Лучший способ может быть просто использовать require() загрузить скрипт.

См. Также тег script в шаблоне / обработчике angular2 при загрузке шаблона dom

Я столкнулся с той же проблемой, но дополнительно мне пришлось загружать несколько скриптов, некоторые из которых могли загружаться параллельно, а другие - последовательно. Это решение будет работать, если вы используете TypeScript 2.1 или выше, который имеет встроенную поддержку async/await и переносится в ES3/ES5:

async ngAfterViewInit() {
  await this.loadScript("http://sub.domain.tld/first-script.js")
  await this.loadScript("http://sub.domain.tld/second-script.js")
}

private loadScript(scriptUrl: string) {
  return new Promise((resolve, reject) => {
    const scriptElement = document.createElement('script')
    scriptElement.src = scriptUrl
    scriptElement.onload = resolve
    document.body.appendChild(scriptElement)
  })
}

Для любых сценариев, которые можно загружать параллельно, вы можете воспользоваться Promise.all:

async ngAfterViewInit() {
  await Promise.all([
    this.loadScript("http://sub.domain.tld/first-parallel.js"),
    this.loadScript("http://sub.domain.tld/second-parallel.js")
  ])
  await this.loadScript("http://sub.domain.tld/after-parallel.js")
}

Примечание. Для отказа от обещания вы можете попробовать scriptElement.onerror = reject в loadScript() Функция, однако, я столкнулся с некоторым странным поведением в этой ситуации. Если вы хотите, чтобы скрипт продолжал загружаться несмотря ни на что, вы можете поэкспериментировать с разрешением обещаний при вызове onerror.

Другие вопросы по тегам