Réévaluer les widgets dans l'en-tête lors du changement de route sans erreur

J’essaie de remplacer ce modèle de widget :

      api.reopenWidget("header-contents", {
        template: hbs`

          {{#if this.site.desktopView}}
            {{#if attrs.sidebarEnabled}}
              {{sidebar-toggle attrs=attrs}}
            {{/if}}
          {{/if}}

          {{home-logo attrs=attrs}}

          {{#if attrs.topic}}
            {{header-topic-info attrs=attrs}}
          {{else if this.siteSettings.bootstrap_mode_enabled}}
            {{#if transformed.showBootstrapMode}}
              {{header-bootstrap-mode attrs=attrs}}
            {{/if}}
          {{/if}}

          <div class="panel clearfix" role="navigation">{{yield}}</div>
        `,
      });

Bien que le modèle soit actuellement identique à l’original dans discourse/app/assets/javascripts/discourse/app/widgets/header-contents.js at 4aa81e709ea49e30383a3a3acd33dfedaebfc240 · discourse/discourse · GitHub

Il génère une erreur :

C’est inattendu, d’autant plus que je ne suis pas en train de « changer quoi que ce soit » (pour l’instant) ?

Je suis capable de reproduire ce problème même si c’est la seule modification.

En fin de compte, la raison pour laquelle j’essaie de changer cela est de forcer une réévaluation de ce modèle même si je ne navigue pas dans ou hors d’une route de sujet.

En fin de compte, je veux ajouter une logique pour forcer le rafraîchissement du widget lors de la navigation dans et hors des routes de catégorie, car ma présentation de route de catégorie doit être différente.

Donc, une solution à cela pourrait être une autre façon de forcer le rafraîchissement du contenu de l’en-tête.

Dans tous les cas, cela ne semble pas se comporter comme je m’y attendrais ?

Nous ne voulons pas vraiment investir beaucoup de temps ici - les widgets ne seront plus là très longtemps. Quelle personnalisation essayez-vous de faire ? Pouvons-nous vous aider en ajoutant une sortie de plugin quelque part (nous avons la possibilité d’ajouter des sorties de plugin normales dans le code des widgets maintenant).

Pouvez-vous partager davantage de votre fichier (par exemple, d’où est importé hbs ?)

1 « J'aime »

Quelle version de Discourse s’agit-il également ? site-header.js:337 ne fait actuellement référence à aucune variable ‘header’

1 « J'aime »

Compris.

import { hbs } from "ember-cli-htmlbars";

Fonctionnellement, j’essaie d’échanger le logo en fonction de la route. En réalité, je le fais en attachant une image au logo d’accueil sur certaines routes et en superposant le logo principal. Je veux que cette logique soit réévaluée lors du passage d’une route à l’autre, ce qui semble actuellement fonctionner lors de l’entrée et de la sortie des routes de sujet, je suppose parce que le widget header-contents auquel tout est attaché a une logique qui évalue les attrs.topic qui change évidemment lorsque cela se produit.

Mon category-logo-widget est attaché comme ceci :

      api.decorateWidget("home-logo:after", (helper) => {
        const currentPath = helper.register
          .lookup("service:router")
          .get("_router.currentPath");

        if (
          helper.widget.currentUser &&
          !helper.widget.site.mobileView &&
          currentPath.indexOf("discovery") === -1
        ) {
          return helper.attach("category-logo-widget");
        }
      });

Ce qui fonctionne bien, mais n’est pas réévalué entre certaines transitions de route, ne répond donc pas entièrement à l’exigence de manière dynamique sans rechargement de page.

Oups, cela pourrait être le problème, j’avais le sentiment que c’était le cas, mais mes tests étaient évidemment trop superficiels pour l’exclure.

Je vois ce commit, je devrai mettre à jour mon instance de développement… PERF: Memoize element references for `dockCheck` (#21079) · discourse/discourse@db16700 · GitHub

Je vais annuler dans tous les cas, merci pour votre temps !

C’est probablement le problème. Les widgets ‘templates’ sont une chose personnalisée de Discourse, et sont compilés d’une manière totalement différente des templates Ember. Vous devrez importer hbs comme ceci :

Il semble que nous ayons un événement d’application site-header:force-refresh que vous pourriez déclencher en réponse à un autre événement d’application ou à un événement de routeur Ember :

(exemple de déclenchement ici)

3 « J'aime »

Génial, merci David, je vais corriger l’installation obsolète et essayer tes recommandations ici aussi. Accumulation multiple, merci de m’avoir aidé à clarifier !

3 « J'aime »

Donc, probablement un peu gratuit, mais j’ai fini par utiliser votre suggestion, avec :

      api.onPageChange(url =>  {
        const applicationController = container.lookup(
          "controller:application"
        );
        applicationController.appEvents.trigger(
          "site-header:force-refresh"
        );
      });

cela a très bien fonctionné, bien que ce ne soit pas parfaitement synchronisé avec la transition de route, mais ce n’est pas grave.

Merci encore !

3 « J'aime »

Au fait, juste pour information, bien que l’API des widgets soit très personnalisée et quelque peu délicate (surtout le code hyperscript), je dois admettre qu’elle est extrêmement puissante pour attacher de nouveaux comportements à des widgets existants sans avoir à remplacer beaucoup de code.

Par exemple, j’ai beaucoup utilisé ce modèle :

api.reopenWidget('discourse-awesome-widget', {

  html(attrs, state) {
    let contents = this._super(...arguments);

    contents.unshift(h("div.my-cool-new-thing", "cool new thing"))

    return contents;
  }
});

this._super pourrait représenter beaucoup de code !!!

Et cela peut devenir beaucoup plus intelligent que cela, au point que j’en suis venu à l’apprécier vraiment.

J’espère que l’“override-ability” de ce qui le remplacera sera tout aussi flexible et puissant.

1 « J'aime »

La solution principale ici sera les points de sortie des plugins. Comme toujours, si vous estimez en avoir besoin d’un qui n’existe pas, n’hésitez pas à soumettre une PR au cœur :rocket:

1 « J'aime »

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