Home > Blockchain >  How to client-side sort inertia data?
How to client-side sort inertia data?

Time:10-17

I have a component that receive data. In my controller I have:

route::get('/', function() { return inertia('foo', ['data' => Model::all()]) });

On my Vue component:

<template>
   <ul> 
      <li v-for="item in data">{{item.name}}</li>
   </ul>
</template>
<script setup>
defineProps({ data: Object })
</script>

My goal is to be able to display the data either by name or score depending on the value of a checkbox. I don't think it is a good idea to send the request on the server-side, so I would like to do it on the component.

Unfortunately, props are read only, and it is not possible to do something like this:

 <li v-for="Object(data).sort((a, b) => b.score - a.score)">

Any other suggestion?

The type of my props.data is:

Proxy {0: {…}, 1: {…}, 2: {…}, 3: {…}, 4: {…}, 5: {…}, 6: {…}, 7: {…}, 8: {…}, 9: {…}, 10: {…}, 11: {…}, 12: {…}, 13: {…}, 14: {…}, 15: {…}, 16: {…}}
[[Handler]]: Object
[[Target]]: Object
0: {id: 1, user: null, name: 'foobar', score: 0, …}
1: {id: 2, user: null, name: 'baz', score: 10, …}

And Object(props.data) doesn't have a sort method.

CodePudding user response:

<script setup>
import { ref, computed } from "vue";
const props = defineProps({ data: Object });
const sortByScore = ref(true);
const sortBy = computed(() => sortByScore.value ? 'score' : 'name')
const sortedData = computed(() =>
  props.data.sort((a, b) => b[sortBy.value] - a[sortBy.value])
);
</script>

And link sortByScore to the checkbox.


I don't like having to deal with .value in my controllers, so I'd write it as:

import { reactive, computed, toRefs } from "vue";
const props = defineProps({ data: Object });
const state = reactive({
  sortByScore: true,
  sortBy: computed(() => state.sortByScore ? 'score': 'name'),
  sortedData: computed(() =>
    props.data.sort((a, b) => b[state.sortBy] - a[state.sortBy])
  )
})

// expose state, so you don't have to use `state.sortedData` in `<template>`
const { sortByScore, sortBy, sortedData } = toRefs(state);

I find reactive() syntax cleaner, especially in large controllers.
Another advantage of this syntax is you can type the state using only one interface.

Another thing I've seen others do is to name state as S and no longer unwrap it for <template>. Just use it as S.sortByScore, S.sortedData, etc.
This way you don't have to re-type all the keys you want exposed. Sometimes I wish there was an equivalent for return {...toRefs(state)} in <script setup>.

CodePudding user response:

Give a try to computed property

<script setup>
import { computed } from 'vue'
const props = defineProps({ data: Object })

const sortedData = computed(() => Object(props.data.value).sort((a, b) => b.score - a.score))
</script>

Also, in your v-for don't forget the :key with a UUID preferably!

  • Related