Come aggiungere manualmente contenuti a pluginOutlet dopo una chiamata ajax? E come reindirizzare o aggiornare un pluginOutlet?

Ciao, :wave:

Sono nuovo al theming di Discourse e a emberjs, e sto attualmente lavorando su un tema che ha elementi di navigazione dal sito web principale.
Gli elementi del menu json provengono da una richiesta ajax e devo visualizzarli in 2 posizioni.
La 1a posizione è header-buttons:before. Sono riuscito a farlo con api.decorateWidget e attivando gli eventi dell’app site-header:force-refresh.

ajax( settings.site_navigation_links_endpoint ).then((result) => {

	if (!result.length) {
		return;
	}

	result.map((customHeaderLinksArray) => {

		const anchorAttributes = {
			title  : customHeaderLinksArray.title,
			href   : customHeaderLinksArray.url,
			target : "self"
		};

		headerLinks.push(
			h(
				`li.custom-header-nav-item`,
				h( "a.custom-header-nav-item-link", anchorAttributes, customHeaderLinksArray.title )
			)
		);

	});

	headerNav = h("ul.custom-header-nav", headerLinks);

	if( settings.site_navigation_position == "inline" ) {
		api.decorateWidget("header-buttons:before", (helper) => {
			return headerNav;
		});
	}

	appEvents.trigger("site-header:force-refresh");

	// Per visualizzare nella posizione (2a posizione, vedi sotto)
	// ...
	// ...
}

La 2a posizione è tramite pluginOutlet, below-site-header.
Credo di non poter fare la stessa cosa di cui sopra, usando api.decorateWidget, perché questo è un pluginOutlet non un widget(?).

Le mie domande sono:

  1. Come inserire manualmente il contenuto ajax nel pluginOutlet?
  2. Vorrei anche sapere come compilare un virtual-dom al volo dopo la mia chiamata ajax? Ad esempio, la variabile sopra, headerNav, vorrei ottenere un markup HTML compilato da essa. Non sono sicuro di quale libreria / funzione usare.
  3. Se possibile, come re-renderizzare anche un pluginOutlet? Simile a appEvents.trigger("site-header:force-refresh");

Grazie in anticipo! :man_bowing:

2 Mi Piace

Corretto. Ci sono due modi per procedere…

  1. Puoi rendere la tua personalizzazione un widget, e poi montare il widget nell’outlet del plugin in questo modo:

    {{mount-widget widget="nome-widget"}}
    

    Puoi vedere un esempio di come viene creato un widget in Discourse, ad esempio il logo della home: discourse/app/assets/javascripts/discourse/app/widgets/home-logo.js at 2dbcea9eeeb816dda347027497b3a49634ef851f · discourse/discourse · GitHub

    In un tema, aggiungeresti il tuo file nome-widget.js a una directory javascripts/discourse/widgets.

    C’è altro sui widget in A tour of how the Widget (Virtual DOM) code in Discourse works, ma tieni presente che stiamo gradualmente eliminando i widget, quindi tutto ciò che imparerai in questo processo non sarà utile a lungo termine.

  2. Mantieni il tuo decoratore di widget così com’è, e crea un componente Ember separato che faccia ciò che desideri nell’outlet del plugin. Stiamo eliminando gradualmente i widget a favore dei componenti Ember (che è ciò su cui si basa la maggior parte di Discourse).

    Questo processo assomiglierebbe a questo:

    1. Crea un file JS e HBS (template) del componente nella directory javascripts/discourse/components del tuo tema.

      • nome-componente.js

      • nome-componente.hbs

    2. Costruisci il tuo componente Ember… purtroppo questo passaggio è essenzialmente “impara Ember” (Guide Ember) … ma penso che questo possa darti un’idea generale per iniziare:

      • In nome-componente.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(); // assumendo che sia json
              this.navLinks = data;
            } catch (error) {
              console.error("Failed:", error);
            }
          }
        }
        
      • In nome-componente.hbs:

        <div {{did-insert this.fetchNavLinks}}>
          {{#each this.navLinks as |link|}}
            <a href={{link.anchor}}>{{link.title}}</a>
          {{/each}}
        </div>
        

        Questo chiamerà l’azione fetchNavLinks ogni volta che il componente viene inserito (in questo caso, quando visiti il sito Discourse e l’app viene renderizzata). Ogni volta che navLinks viene aggiornato, il contenuto del componente si aggiornerà perché è una proprietà tracciata.

        Se vuoi aggiornare i link più spesso che al rendering del componente, dovrai aggiungere altra logica al JS qui… controllando se il percorso corrente (pagina) soddisfa determinate condizioni, ad esempio.

    3. Questo componente verrebbe aggiunto a un outlet del plugin aggiungendolo all’outlet in javascripts/discourse/connectors/below-site-header/my-component-connector.hbs:

      <ComponentName />
      
9 Mi Piace

Grazie mille Kris! È molto utile.

Ho optato per il secondo approccio, utilizzando il componente, poiché i widget stanno gradualmente venendo eliminati. A parte il piccolo errore di battitura nella chiamata della funzione, nel file .hbs dovrebbe essere {{did-insert this. fetchNavLinks}}, tutto funziona!

È bello sapere che abbiamo did-insert, è un grande sollievo! Ho finito il compito. :man_bowing:

1 Mi Piace

ah, sono contento che tu l’abbia notato, ho corretto il mio post qui sopra

1 Mi Piace

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.