JSで連想配列の配列を任意のキーで並び替える【JavaScript】【Rails】


したいこと

データベースから取ってきたデータをフロント(JS)で任意のカラムで並び変えて表示したい(APIに何回もアクセスしたくないため)

コード

JS

export let sortItems = (items, sortType, order) => {
    return items.sort((a, b) => {
        if (order == "ASC") {
            return (a[sortType] < b[sortType] ? 1 : -1)
        } else { // DESC
            return (a[sortType] > b[sortType] ? 1 : -1)
        }
    })
}

itemsは連想配列の配列。sortTypeはカラム名(連想配列のキー)。orderは"ASC"か"DESC"。
ただこのままだと更新日時で並び変えた場合に昇順と降順が逆になってしまうので、データを加工する

Rails

Railsの場合

<Active Recode>
&.map {|g| 
    {
      **g.attributes, 
      updated_at_in_ms: (Time.now - g.updated_at).to_f * 1000
    }
}

数値に変換して符号を逆にしている(現在時刻から引く必要はとくにない)

おまけ

Vueコンポーネントで使う

sortTypesは {キー: 表示用文字列, ...}の形にしてselect要素で選択できるようにする

{name: "Name", updated_at_in_ms: "Updated"}
<template>
    <select v-model="sort">
        <option v-for="(value, key) in sortTypes" :value="key">{{value}}</option>
    </select>
    <select v-model="order">
        <option value="ASC">Asc</option>
        <option value="DESC">Desc</option>
    </select>
</template>

<script>
export default {
    props: {
        sortTypes: {
            type: Object,
            default: () => ({}),
        }
    },
    data: () => ({
        sort: "updated_at_in_ms",
        order: "DESC"
    }),
    watch: {
        sort: function () {
            this.$emit("changeSort", this.sort);
        },
        order: function () {
            this.$emit("changeOrder", this.order);
        }
    }
}
</script>

親コンポーネントで使うにはcomputedで冒頭のを返すように、かつ子と同じようにdataにsortとorder、sortTypesを設定して

<Sort
    @changeSort="sort = $event"
    @changeOrder="order = $event"
    :sortTypes="sortTypes"
/>