Soy nuevo en la tematización de Discourse y emberjs, y actualmente estoy trabajando en un tema que tiene elementos de navegación del sitio web principal.
Los elementos de navegación JSON provienen de una solicitud ajax y necesito mostrarlos en 2 ubicaciones.
La primera ubicación es header-buttons:before. Logré hacerlo con api.decorateWidget y activando los eventos de la aplicación site-header:force-refresh.
La segunda ubicación es a través de pluginOutlet, below-site-header.
Creo que no puedo hacer lo mismo que lo anterior, usando api.decorateWidget, porque esto es un pluginOutlet, ¿no un widget?
Mis preguntas son:
¿Cómo inserto manualmente contenido ajax en el pluginOutlet?
También me gustaría saber cómo compilar un virtual-dom sobre la marcha después de mi llamada ajax. Por ejemplo, la variable anterior, headerNav, me gustaría obtener una representación HTML compilada de ella. No estoy seguro de qué biblioteca/función usar.
Si es posible, ¿cómo volver a renderizar también un pluginOutlet? similar a appEvents.trigger("site-header:force-refresh");
En un tema, añadirías tu archivo widget-name.js a un directorio javascripts/discourse/widgets.
Hay más información sobre widgets en A tour of how the Widget (Virtual DOM) code in Discourse works, pero ten en cuenta que vamos a eliminar gradualmente los widgets, por lo que cualquier cosa que aprendas en este proceso no será útil a largo plazo.
Mantén tu decorador de widget como está y crea un componente Ember separado que haga lo que quieras en el plugin outlet. Hemos estado eliminando gradualmente los widgets en favor de los componentes Ember (que es en lo que se basa la mayor parte de Discourse).
Este proceso se vería así:
Crea un archivo JS y HBS (plantilla) del componente en el directorio javascripts/discourse/components de tu tema.
component-name.js
component-name.hbs
Construye tu componente Ember… desafortunadamente este paso es esencialmente “aprender Ember” (Guías de Ember) … pero creo que esto te dará una idea aproximada para empezar:
En component-name.js:
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
const endpoint = settings.site_navigation_links_endpoint;
export default class ComponentName extends Component {
@tracked navLinks = null;
@action
async fetchNavLinks() {
try {
const response = await fetch(endpoint);
const data = await response.json(); // asumiendo que es json
this.navLinks = data;
} catch (error) {
console.error("Falló:", error);
}
}
}
Esto llamará a la acción fetchNavLinks cada vez que se inserte el componente (en este caso, cuando visites el sitio de Discourse y la aplicación se renderice). Cada vez que navLinks se actualice, el contenido del componente se actualizará porque es una propiedad rastreada.
Si quieres actualizar los enlaces con más frecuencia que al renderizar el componente, necesitarás añadir algo más de lógica al JS aquí… comprobando si la ruta actual (página) cumple ciertas condiciones, por ejemplo.
Este componente se añadiría a un plugin outlet añadiéndolo al outlet en javascripts/discourse/connectors/below-site-header/my-component-connector.hbs:
Opté por el segundo enfoque, usando componentes, ya que los widgets están siendo gradualmente eliminados. Aparte del pequeño error tipográfico en la llamada a la función, en el archivo .hbs debería ser {{did-insert this. fetchNavLinks}}, ¡todo funciona!
Me alegra saber que tenemos did-insert, es un gran alivio. He terminado la tarea.