Addepar / ember-table

https://opensource.addepar.com/ember-table/
Other
1.7k stars 351 forks source link

Custom cellComponent not updating on sorting #898

Open crozarakamilla opened 3 years ago

crozarakamilla commented 3 years ago

I have some custom cell components that renders different colors and labels depending on the current row value. It renders just fine but when I sort the table data the cells with these custom components doesn't update, it still the same label and the same colors of the first time it was rendered.

That's my table:

<EmberTable as |t|>
        <t.head
          @columns={{@columns}} 
          @widthConstraint='gte-container' 
          @resizeMode='standard' 
          @fillMode="equal-column"
          @sorts={{this.sorts}}
          @onUpdateSorts={{action (mut this.sorts)}} as |h|>
          <h.row  as |r|>
            {{#if r.columnValue.hideValue}}
            {{else}}
            <r.cell as |columnValue columnMeta|>
              {{columnValue.name}}
            </r.cell>
            {{/if}}
          </h.row>
        </t.head>

        <t.body @rows={{this.rows}} as |b|>
          <b.row as |r|>
            {{#if r.columnValue.hideValue}}
            {{else}}
              <r.cell as |cell column row|>
                  {{if column.cellComponent}}
                    {{component column.cellComponent object=row}}
                  {{else}}
                    {{cell}}
                  {{/if}}
              </r.cell>
            {{/if}}
          </b.row>
        </t.body>
</EmberTable>

And the column's definition:

columns = [
    {
      cellComponent: "utils/edit-record",
    },
    {
      name: "Vehicle",
      valuePath: "vehicle.plate",
    },
    {
      name: "Status",
      valuePath: "state.state",
      cellComponent: "utils/format-state",
      width: 150,
    },
  ];

And the component to format the state:

import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";

export default class FormatStatusComponent extends Component {
  @tracked color = "gray-500";
  @tracked textColor = "jet";
  @tracked status = null;

  constructor(owner, args) {
    super(owner, args);

    this.status = this.args.object.get("status.status");

    switch (this.status) {
      case "Booked":
        this.color = "lazulli";
        this.textColor = "white";
        break;
      case "Waiting cleaning":
        this.color = "sunglow";
        this.textColor = "black";
        break;
      case "Bloqued":
        this.color = "light-red";
        this.textColor = "white";
        break;
      case "Canceld":
        this.color = "light-red";
        this.textColor = "white";
        break;
      default:
        this.color = "light-red";
        this.textColor = "white";
    }
  }
}
<div class="mr-2 bg-{{this.color}} text-{{this.textColor}} p-2 pr-4 pl-4 rounded leading-none flex items-center justify-center font-semibold">
  {{this.status}}
</div>

When I click on table's header to sort rows it sorts all the info correctly but the info that is rendered using this custom component still the same. It doesn't change neither the label or the colors.

Which would be the best approach to get this to work? Am I missing something here?

niksa88 commented 3 years ago

Hi @crozarakamilla you must on sort reset color and textColor.

You can do that with this addon https://github.com/emberjs/ember-render-modifiers

<div {{did-update this._reset @object}} class="mr-2 bg-{{this.color}} text-{{this.textColor}} p-2 pr-4 pl-4 rounded leading-none flex items-center justify-center font-semibold">
{{this.status}}
</div>

and than in component on _reset action you reset values.

@action
_reset() {

this.status = this.args.object.get("status.status");

switch (this.status) {
      case "Booked":
        this.color = "lazulli";
        this.textColor = "white";
        break;
      case "Waiting cleaning":
        this.color = "sunglow";
        this.textColor = "black";
        break;
      case "Bloqued":
        this.color = "light-red";
        this.textColor = "white";
        break;
      case "Canceld":
        this.color = "light-red";
        this.textColor = "white";
        break;
      default:
        this.color = "light-red";
        this.textColor = "white";
    }
}

I didn't tested but I think it will work.

crozarakamilla commented 3 years ago

Thank you! It works like a charm!