0

My goal is to be able to sort DEST or ASC the table. To do this, in the array 'tableItems' I get unformatted numbers, which I format to have the dot for thousands and the comma for decimals with the 'numericValues' method. This method returns numeric data, but in strings.

numericValues() {
    const numberFormat = new Intl.NumberFormat('de');

    this.tableItems.forEach((item) => {
      for (const key in item) {
        if (typeof item[key] === 'number') {
          const formattedValue = numberFormat.format(item[key]);

          item[key] = formattedValue;
        }
      }
    });
 }

I would like to be able to sort the table these strings but as if they were numbers. To do this, I have added the line ':custom-sort="customSort"' in my template.

The problem of having added the 'customSort' method, is that sort no longer works in my table, when I click on the headers

So, I show what I have tried to do with the method I add in custom-sort:

This is my template:

<v-data-table
          :headers="tableHeaders"
          :items="tableItems"
          :items-per-page="18"
          :search="search"
          class="elevation-1"
          :style="getTableHeight()"
          :custom-sort="customSort"
></v-data-table>

This is my method customSort:

customSort(tableItems: any[], index: number, isDescending: boolean): any[] {
    return tableItems.sort((a, b) => {
      console.log(a)
      const valueA = a;
      const valueB = b;

      if (typeof valueA === 'string' && typeof valueB === 'string') {
        const numA = Number(valueA);
        const numB = Number(valueB);

        if (!isNaN(numA) && !isNaN(numB)) {
          return isDescending ? numB - numA : numA - numB;
        }
      }

      return isDescending ? String(valueB).localeCompare(valueA) : String(valueA).localeCompare(valueB);
    });
}

Can anyone give me some advice on what I am doing wrong?

2
  • Remove the custom sort and v-data-table will sort according to the primitive data type. If these are Number - then they will be sorted numerically. You should format the values in the template only - not in the raw data. Simply use the corresponding slot for the given column. Commented Jun 20, 2023 at 8:54
  • Yes. Probably I have to delete the method 'numericValues', it will works. But I need the dots in the thousands and comma in decimals. If I use 'numericValues' I have String, but I need numeric type. Commented Jun 20, 2023 at 9:25

2 Answers 2

0

I finally solved it as follows:

In the <v-data-table> component I added a <template> tag to customize the appearance and formatting of the data in the table.

<v-data-table
    :headers="tableHeaders"
    :items="tableItems"
    :items-per-page="18"
    :search="search"
    class="elevation-1"
    :style="getTableHeight()"
        >
        <template
          v-for="(headerItem, index) in tableHeaders"
          v-slot:[`item.${headerItem.value}`]="{ item }"
        >
          {{ headerItem.formatter ? headerItem.formatter(item[headerItem.value]) : item[headerItem.value] }}
        </template>
</v-data-table>

Finally, the method where it loaded the headers, added the formatting.

loadTableHeaders() {
    let aliases = [];
    aliases = this.$store.state.informes.dataInformes.get('aliases')?.filter((item: any) => item.endpoint === this.config.sources).sort((a: any, b: any) => (a.order < b.order ? -1 : 1));
    if (!aliases) {
      aliases = this.$store.state.informes.dataInformes.get(this.config.sources); // FIXME: Ordenar headers cuando no existan aliases
    }
    aliases.forEach((item: any) => {
      if (item.alias !== 'Nivel Territorial') {
        if ((informesStore.state.nivTerr !== 'CC.AA' && informesStore.state.nivTerr !== 'Nacional')
          || ((informesStore.state.nivTerr === 'CC.AA' || informesStore.state.nivTerr === 'Nacional') && item.alias !== 'Ámbito superior')) {
            this.tableHeaders.push({ text: item.alias, value: item.indicator, formatter: this.formatNumericValues });
        }
      }
    });
  }

  formatNumericValues(value: any) {
    if (typeof value === 'number' && !isNaN(value)) {
      return new Intl.NumberFormat('de').format(value);
    } else {
      return value; // Devuelve el valor sin formato para casos no numéricos
    }
  }
Sign up to request clarification or add additional context in comments.

Comments

0

There are several issues:

  • The types of customSort() does not match that of :custom-sort. Your index is declared as number, but it is actually a string array (sortBy), and your isDescending (sortDesc) is actually a boolean array. You could have just copied the declaration from the documentation...
  • You logged the variable, so you are probably aware that the input to sort() is the whole object, not just the value. So when you assign the whole object to valueA and valueB respectively, none of the following comparisons will work. You need to extract the values using the props in sortBy.
  • A number in a local format, like german 1.000,56, cannot be transformed back to a number with Number(), you either need to parse it back or, preferably, keep the original number somewhere on your object and fall back to it during sorting.
  • If you want to be able to sort by multiple values, you need to go through the sortBy array and compare each field until you get a non-zero value.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.