Live updates of components

AI-generated summary

Live Updates of Components

The discussion revolves around updating radio buttons live after a user changes their rating. pfaffman initially has a component that works as expected but fails to update live.

The issue arises from the use of get instead of @discourseComputed or @tracked. pfaffman attempts to use @discourseComputed but encounters an error and is advised to use tracked from @glimmer/tracking instead.

To fix the issue, pfaffman imports tracked and applies it to the myRating property. The property is initialized in the constructor, and its value is updated in the action that changes the rating. This allows the radio buttons to update live when the user changes their rating.

I have a component that looks like this:

<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>

The ratings are an array added to the topic_view serializer and have topic_id and rating_id in each array item.

And I have this supporting js:

...
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;
  }
...

It works as expected. And when I click on of the RadioButtons it calls a function that does a POST and updates a custom model that’s added to the topic serializer. If I reload the page, everything is expected, but I want those radio buttons to update live (right now, multiple radio buttons remain lit if you change it multiple times).

My controller does this:

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

So I think the stuff should be getting updated in the topics displayed in the topic list.

I think the issue is that I need to be using @discourseComputed instead of get, but when I do, I get an error. Maybe I can’t use @discourseComputed in a component? Maybe I need to do some kind of . . . something else?

EDIT: I asked chatGPT and it says that I need do so something with
import { tracked } from '@glimmer/tracking';, so I’m trying that now. . .

So I did it. I think that these bits might be helpful for someone else, so here’s what I was missing in the component:

This is far from generally useful documentation, but maybe it will help someone if they need it (or maybe I’ll find it next time I need it!).

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

 constructor() {
    super(...arguments);
    this.userRatings = this.args.topic.user_ratings;  // Initialize tracked property
    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;
    }

....
 // and then in the action that changes the value:
        this.myRating = Number(newStatus);