Come iniettare un servizio in discourse?

Voglio utilizzare un servizio in un componente del tema che sto creando. Se i servizi sono disponibili solo nei plugin, posso anche creare un plugin. L’obiettivo è collegare due diversi plugin outlet: premere un pulsante in un outlet e far sì che quella pressione del pulsante venga rilevata dall’altro outlet.

Come posso registrare correttamente un servizio in Discourse? Ho seguito l’argomento qui e il codice correlato del plugin su GitHub, ma non sono riuscito a farlo funzionare.

Penso che il pezzo mancante sia che il mio componente del tema non riconosce il servizio. (Ho provato anche in un plugin, con lo stesso risultato).


Ecco del codice che ho provato:

javascripts/discourse/services/great-stuff.js:

import Service, { inject as service } from "@ember/service";

export default class GreatStuffService extends Service {
    call() {
        console.log('you called it')
    }
}

connectors/topic-list-after-title/sample-outlet.js.es6:

import { inject as service } from "@ember/service";

export default {
  greatStuff: service(),
  actions: {
      buttonPressInOutlet(){
         this.greatStuff.call()
     }
  }
}

Quando chiamo l’azione “buttonPressInOutlet()”, ottengo l’errore: Uncaught TypeError: Cannot read properties of undefined (reading 'call').

Cos’altro è richiesto?

Potresti voler dare un’occhiata a come sono scritti gli altri servizi. Non credo che la sintassi x estende y funzioni ancora sulla versione di Ember che Discourse utilizza.

Inoltre, potresti voler dare un’occhiata all’API appEvents per comunicare tra due componenti.

2 Mi Piace

Il problema qui è che il ‘connettore’ non è un EmberObject, e quindi non puoi iniettare cose al suo interno. Invece, dovrai creare un componente Ember e iniettarlo lì.

Il tuo template ‘connettore’ assomiglierebbe quindi a qualcosa del genere

{{my-component-name}}

Ecco un esempio di come viene fatto nel plugin whos-online:

Abbiamo un servizio nel core:

Un template connettore nel plugin

La definizione del componente:
https://github.com/discourse/discourse-whos-online/blob/main/assets/javascripts/discourse/components/whos-online.js#L6-L7

(o puoi usare export default Component.extend({ whosOnline: service() }) se preferisci)

E il template del componente:
https://github.com/discourse/discourse-whos-online/blob/main/assets/javascripts/discourse/templates/components/whos-online.hbs

3 Mi Piace

Non ci avevo pensato. Grazie per l’idea!


@david: ti ringrazio molto per questa spiegazione e per gli esempi di codice. Con questi esempi, sono riuscito a farlo funzionare per fare clic su un pulsante in un componente e farlo chiamare un’azione nel servizio. Questo è un grande passo avanti.

Ora sto cercando di risolvere l’altra metà: una volta che un’azione viene chiamata in un servizio, far sì che ciò attivi un’azione in un componente. Immagino sia qualcosa del tipo, nel servizio, importare il componente e chiamare una funzione in quel componente (e/o sottoscrivere l’azione nel componente). Ma non ho ancora capito la sintassi.

Supponendo che sia corretto, hai qualche esempio di sintassi?

Chiamare un metodo di componente da un servizio non è una buona prassi e Ember non offre un modo semplice per farlo. Ci possono essere più istanze di un componente, quindi come farebbe il servizio a sapere quale attivare l’azione?

Detto questo, a volte può essere necessario far funzionare qualcosa all’interno del sistema di plugin outlet di Discourse.

Consiglierei lo stesso di @fzngagan: dai un’occhiata a appEvents. Probabilmente sono il modo più pulito per attivare la logica del componente da un servizio.

2 Mi Piace

Pensavo che fosse questo lo scopo di evented, ma non l’ho mai usato prima. L’obiettivo è solo quello di ottenere una configurazione simile a ipc dove

  • l’utente fa clic sul pulsante nel componente A
  • quel clic causa il caricamento dei dati nel componente B

Ho più familiarità con Angular, dove creare e poi sottoscrivere un servizio sarebbe il modo generale per farlo. Ma in Discourse il modo migliore è appEvents?

Esatto! appEvents è un wrapper per Evented. Se preferisci usare Evented direttamente, va benissimo anche quello :+1:

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/services/app-events.js#L4

1 Mi Piace

:slight_smile: Interessante! Grazie per il follow-up. Non ho preferenze per evented - non l’ho mai usato prima e stavo lottando un po’ con la sintassi in un servizio Discourse:
export default class GreatStuffService extends Service.extends(Evented, {...})
non è del tutto corretto.

Non ho usato nemmeno appEvents prima. Sono in grado di creare un nuovo appEvent in un plugin/componente tema a cui posso poi sottoscrivermi? La maggior parte degli esempi che trovo riguardano la sottoscrizione ad appEvents già definiti nel core di Discourse.

1 Mi Piace

Sì, puoi farlo. Cerca appEvents.trigger

2 Mi Piace