Reavaliar widgets no cabeçalho após mudança de rota sem erro

Estou tentando substituir este template 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>
        `,
      });

Apesar do template ser atualmente idêntico ao original em discourse/app/assets/javascripts/discourse/app/widgets/header-contents.js at 4aa81e709ea49e30383a3a3acd33dfedaebfc240 · discourse/discourse · GitHub

Ele está gerando um erro:

Isso é inesperado, especialmente porque eu não estou realmente “mudando nada” (ainda)?

Consigo reproduzir este problema mesmo que esta seja a única modificação.

Em última análise, a razão pela qual estou tentando mudar isso é para forçar uma reavaliação deste template, mesmo que eu não esteja entrando ou saindo de uma rota de tópico.

Em última análise, quero adicionar lógica para que o widget seja forçado a atualizar ao entrar e sair de rotas de categoria, porque a apresentação da minha rota de categoria precisa ser diferente.

Portanto, uma solução para isso pode ser outra maneira de forçar a atualização do conteúdo do cabeçalho.

Em qualquer caso, isso não parece estar se comportando como eu deveria esperar?

Não queremos investir muito tempo aqui - os widgets não vão durar muito mais tempo. Que personalização você está tentando fazer? Podemos ajudar adicionando um ponto de saída de plugin em algum lugar (agora temos a capacidade de adicionar pontos de saída de plugin normais dentro do código do widget).

Você pode compartilhar mais do seu arquivo (por exemplo, de onde hbs está sendo importado?)

1 curtida

Além disso, qual versão do Discourse é esta? site-header.js:337 não referencia atualmente uma variável ‘header’

1 curtida

Entendido.

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

Funcionalmente, estou tentando trocar o logotipo dependendo da rota. Na realidade, estou fazendo isso anexando uma imagem ao logotipo inicial em algumas rotas e sobrepondo o logotipo principal. Quero que essa lógica seja reavaliada ao mudar de rota, o que atualmente parece funcionar ao entrar e sair das rotas do Tópico, suponho que porque o widget header-contents ao qual tudo está anexado tem lógica avaliando os attrs.topic, que obviamente muda quando isso ocorre.

Meu category-logo-widget está anexado assim:

      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");
        }
      });

O que funciona bem, mas não está sendo reavaliado entre certas transições de rota, portanto, não está cumprindo o requisito de ser totalmente dinâmico sem uma recarga de página.

Ooooops, este pode ser o problema, eu tinha a sensação de que poderia ser, mas meus testes foram obviamente muito superficiais para descartar isso.

Vejo este commit, precisarei atualizar minha instância de desenvolvimento… PERF: Memoize element references for `dockCheck` (#21079) · discourse/discourse@db16700 · GitHub

Vou reverter de qualquer maneira, obrigado pelo seu tempo!

Este é provavelmente o problema. Os ‘templates’ de Widget são uma coisa personalizada do Discourse e são compilados de uma maneira totalmente diferente dos templates do Ember. Você precisará importar hbs assim:

Parece que temos um site-header:force-refresh appEvent que você poderia acionar em resposta a algum outro appEvent ou evento do roteador Ember:

(exemplo de gatilho aqui)

3 curtidas

Ótimo, obrigado David, vou corrigir a instalação desatualizada e tentar suas recomendações aqui também. Acúmulo múltiplo, obrigado por ajudar a esclarecer!

3 curtidas

Então, provavelmente um pouco gratuito, mas acabei usando sua sugestão, com:

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

que funcionou muito bem, embora não sincronize perfeitamente com a transição da rota, mas tudo bem.

Obrigado novamente!

3 curtidas

aliás, só uma nota paralela aqui, embora a API de widgets seja toda muito personalizada e um tanto complicada (especialmente as coisas do hyperscript), devo admitir que é extremamente poderosa para anexar novos comportamentos a widgets existentes sem ter que substituir muito código.

por exemplo, usei muito este padrão:

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 poderia ser muito código!!!

E pode ficar muito mais inteligente do que isso, a ponto de eu ter passado a apreciá-lo muito.

Espero que a “capacidade de substituição” do que quer que o substitua seja igualmente flexível e poderosa.

1 curtida

A principal solução aqui serão os “plugin outlets”. Como sempre, se você sentir que precisa de um que não existe, sinta-se à vontade para fazer um PR para o core :rocket:

1 curtida

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