Тег 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.