Atualizações ao vivo dos componentes

Tenho um componente que se parece com isto:

<td class="topic-rating">
  <span class="rating-title">{{ratingName}}</span> 
     <form>
        <input type="hidden" name="topic_id" value="{{topic.id}}">
        {{#unless useNames}}{{ratingLow}}{{/unless}}
        {{#each this.ratingOptions as |option|}}
            <RadioButton
              @name={{option.name}}
              @value={{option.value}}
              @selection={{this.myRating}}
              @onChange={{this.submitRating}}
            />
            {{#if useNames}} <span class="rotated-label">{{option.label}}</span>{{/if}}
        {{/each}}
        {{#unless useNames}}{{ratingHigh}}{{/unless}}
    </form>
</td>

As classificações são um array adicionado ao serializador topic_view e têm topic_id e rating_id em cada item do array.

E tenho este JavaScript de suporte:

...
export default class TopicRatingComponent extends Component {
  get myRating() { 
    const ratingId = this.args.id;
    const rating = this.args.topic.user_ratings.find((rating) => Number(rating.rating_id) === Number(ratingId));
    return rating?.rating_value;
  }
...

Funciona como esperado. E quando clico num dos RadioButtons, ele chama uma função que faz um POST e atualiza um modelo personalizado que é adicionado ao serializador do tópico. Se eu recarregar a página, tudo está como esperado, mas eu quero que esses botões de rádio sejam atualizados ao vivo (atualmente, vários botões de rádio permanecem acesos se você os alterar várias vezes).

O meu controlador faz isto:

      MessageBus.publish("/topic/#{params[:topic_id]}", reload_topic: true)

Portanto, acho que as coisas deveriam estar a ser atualizadas nos tópicos exibidos na lista de tópicos.

Acho que o problema é que preciso de usar @discourseComputed em vez de get, mas quando o faço, recebo um erro. Talvez eu não possa usar @discourseComputed num componente? Talvez eu precise fazer algum tipo de . . . algo mais?

EDIT: Perguntei ao chatGPT e ele diz que preciso fazer algo com
import { tracked } from '@glimmer/tracking';, então estou a tentar isso agora. . .

1 curtida

Então eu consegui. Acho que essas partes podem ser úteis para outra pessoa, então aqui está o que estava faltando no componente:

Isso está longe de ser uma documentação útil em geral, mas talvez ajude alguém se precisar (ou talvez eu a encontre na próxima vez que precisar!).

import { tracked } from '@glimmer/tracking';
...
  @tracked myRating

 constructor() {
    super(...arguments);
    this.userRatings = this.args.topic.user_ratings;  // Inicializa a propriedade rastreada
    if (!this.args.topic.user_ratings) {
      return [];
    }
    const ratingId = this.args.id;
    const rating = this.args.topic.user_ratings.find((rating) => Number(rating.rating_id) === Number(ratingId));
    this.myRating = rating?.rating_value;
    }

....
 // e então na ação que muda o valor:
        this.myRating = Number(newStatus);
2 curtidas