<div class="subscription-form clearfix">
<h5>Sign Up for Our Blog</h5>
</div>
При первой загрузке страницы всё работает отлично. На последующих страницах (большинство из них, по крайней мере) форма не загружается, и появляется ошибка:
Couldn't find target container .subscription-form for HubSpot Form a86ca9cc. Not rendering form onto the page
Кажется, футер загружается после того, как срабатывает скрипт?
Мне каким-то образом нужно отложить выполнение скрипта до момента загрузки футера.
В plugin-api.js сказано:
// Listen for a triggered `AppEvent` from Discourse.
api.onAppEvent("inserted-custom-html", () => {
console.log("a custom footer was rendered");
});
Возможно, мне просто нужно узнать, какое событие AppEvent следует отслеживать?
Ха! Сработало! (Конечно, это произошло после того, как я убедил их, что то, что они пытались сделать в футере, изначально не стоило делать). Я в полном восторге, что наконец разобрался в этом, и очень ценю вашу помощь; я постепенно начинаю понимать, как всё это работает. (И, думаю, теперь они просто удалят футер целиком.)
Ага! Не знаю, почему я не подумал поискать по слову «footer»!
Так что inserted-custom-html относится к чему угодно в темах? И тогда я могу добавить :footer или :header, или, возможно, :head_tag? В этом и есть магия? Это только у меня так, или было бы полезнее, если бы
JavaScript и Ember — самые сложные для меня вещи, которые я пытаюсь понять, наверное, со времён изучения Lisp в середине 1980-х, поэтому я всё ещё не до конца понимаю, что считается «очевидным».
Не совсем. Это событие срабатывает только при рендеринге ember-компонента custom-html.
Итак, где мы используем этот ember-компонент и что он делает?
Мы в основном используем его в главном шаблоне приложения для рендеринга двух полей темы.
Вкладка темы after_header
Вкладка темы footer
Обратите внимание, что мы используем его и в других местах, но в данном контексте это не имеет значения.
Заметьте, что у футера также есть атрибут triggerAppEvent="true".
Именно поэтому вы можете использовать:
api.onAppEvent("inserted-custom-html:footer", () => {
// какой-то код
});
Вы не можете сделать то же самое с вкладкой after_header. Discourse не генерирует событие для неё. Поэтому это не сработает:
api.onAppEvent("inserted-custom-html:top", () => {
// какой-то код
});
Теперь, почему мы используем этот ember-компонент для рендеринга некоторых полей темы?
Простой ответ: это даёт нам гораздо больше контроля над тем, когда он рендерится.
Два примера этого… Список тем и страница администратора.
Мы не хотим рендерить футер в списке тем, пока ещё есть темы для загрузки через бесконечную прокрутку.
Также мы не хотим рендерить любые баннеры или разметку брендинга сайта на странице администратора, добавленные во вкладке after_header.
Использование ember-компонента custom-html даёт нам более тонкий контроль над такими вещами.
Теперь вернёмся к вашему вопросу. Если вам нужно выполнить какие-то действия при рендеринге футера, вам нужен этот обёртка:
api.onAppEvent("inserted-custom-html:footer", () => {
// какой-то код
});
Этот метод API работает для всех событий приложения. Поэтому, хотя пример в нём не совсем полный, это всего лишь пример. Существует множество других AppEvents, которые вы можете использовать в этом методе. Например, вы можете посмотреть здесь:
чтобы увидеть названия нескольких срабатывающих событий.
this.appEvents.trigger("EVENT_NAME")
и как мы подключаемся к ним, чтобы вносить другие изменения:
this.appEvents.on("EVENT_NAME")
Вы можете подключиться к любому событию, которое генерирует ядро Discourse, в своей теме. Так что, если я хочу выполнить какой-то код прямо перед открытием редактора (composer),
Это отличный ответ, и он настолько понятен, что даже я смог его осмыслить.
Проблема «как заставить что-то сработать» возникает довольно часто. Возможно, люди найдут её здесь, но ваш последний пост вполне мог бы стать отдельной темой и, возможно, быть добавлен или связан в руководствах по темам и/или плагинам.
А теперь, когда под «темой» в основном подразумевается «ember», а под «плагином» — «rails», имеет смысл подумать о некотором рефакторинге этих разделов. Кажется, когда всё только начиналось, было много функционала Ember, который требовал плагина, но теперь это можно реализовать в компоненте темы, верно? А сейчас вы можете реализовать функционал Ember как в плагине, так и в компоненте темы.
Привет, @Johani, вот ещё один вариант проблемы «как вызвать триггер или быть вызванным»: я использую версию плагина Custom Header Links в своём плагине. Он создаёт ссылки на некоторые элементы («серверы»), которые создаются в отдельной модели, добавляемой моим плагином. Когда создаётся server, я хочу перестроить ссылки в заголовке, чтобы они вели на два последних созданных сервера. Сейчас я делаю это в инициализаторе, и всё работает, но для обновления после добавления сервера необходимо перезагрузить страницу.
Ты рассказывал, как добавлять и отслеживать триггеры, поэтому я подумал, что смогу разобраться, но страница, которая выполняет эту работу, находится в discourse-subscriptions. Возможно, мне стоит отправить PR в discourse-subscriptions, чтобы добавить
this.appEvents.trigger("purchase-complete")
после завершения покупки (при этом покупка вызывает добавление в группу, что, в свою очередь, вызывает создание сервера и удаление пользователя из группы). Или, если бы я мог просто вызвать перезагрузку после завершения покупки или после нажатия кнопки «OK» в модальном окне «Покупка завершена», это тоже подошло бы, но я не знаю, как это сделать (то, что я пробовал, приводило к бесконечной перезагрузке страницы…)
Это снова мне помогло! Мне нужно было загрузить скрипт при обновлении потока постов. Все примеры, которые я нашёл, были в компонентах, где appEvent был доступен через this. Наконец я нашёл это, и теперь в apiInitializer я могу сделать так:
api.onAppEvent('post-stream:refresh', args => {
// сделать что-то!!!
});
И теперь эти объявления загружаются при загрузке каждой партии постов. Я уже поставил лайк твоему посту, поэтому решил написать более развёрнутую благодарность.