VueJS 从 JSON 数据转置 table 行到列
VueJS transpose table row to column from JSON data
所以我有 JSON 来自 Laravel API 的数据(由 Axios 调用),我想转置这些数据:
{"message":"Data peserta tahap 1 OR XI","data":[
{"nim":1810112048,"nama":"Annisa indra","id_sk1":11,"nilai":30},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":12,"nilai":30},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":13,"nilai":25},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":21,"nilai":72},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":31,"nilai":57},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":11,"nilai":20},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":12,"nilai":20},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":13,"nilai":10},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":21,"nilai":75},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":31,"nilai":57}
]}
有 5 个重复的 NIM,内容不同 nilai(等级)
这是我的目标:
+------------+------------------------+----+----+----+----+----+
| nim | nama | 11 | 12 | 13 | 21 | 31 |
+------------+------------------------+----+----+----+----+----+
| 1810112048 | Annisa indra | 30 | 30 | 25 | 72 | 57 |
| 1810522038 | Muhammad fakhri naufal | 20 | 20 | 10 | 75 | 57 |
+------------+------------------------+----+----+----+----+----+
这是我的 VueJS 视图代码:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<table class="table">
<thead>
<tr>
<th>NIM</th>
<th>Nama</th>
<th v-for="sk in subkriteria" :key="sk.id_sk1">
{{ sk.sub_kriteria }}</th>
</tr>
</thead>
<tbody>
<template v-if="peserta.array != 0">
<tr v-for="(peserta, index) in penilaian1" :key="index">
<td>{{ peserta.nim }}</td>
<td>{{ peserta.nama }}</td>
<template v-if="peserta.array != penilaian1.array ">
<td v-for="sk in subkriteria" :key="sk.id_sk1">
<i>Tidak ada data</i>
</td>
</template>
<template v-else>
<td v-for="penilaian in penilaian1" :key="penilaian.id_sk1">
{{ penilaian.nilai }}
</td>
</template>
<td>
<div class="btn-group">
<router-link
:to="{ name: 'penilaian1.show', params:{id: penilaian1.id}}"
class="btn btn-sm btn-outline-info">Show</router-link>
</div>
</td>
</tr>
</template>
</tbody>
</table>
<script>
import axios from 'axios'
export default {
computed:{
countedMhs: function() {
return this.peserta.filter(penilaian1 => penilaian1.nim==0);
},
rolesByCategory() {
return _.groupBy(this.penilaian1.nim )
}
},
data: function () {
return {
peserta: [],
penilaian1: [],
subkriteria: [],
kriteria: [],
loading: true,
}
},
mounted() {
this.loadData();
},
watch: {
selected: {
handler: function () {
this.loadData();
},
deep: true
}
},
methods: {
loadData: function () {
this.loading = true;
Promise.all([
this.loadPeserta(),
this.loadPenilaian1(),
this.loadTableSK1(),
this.loadTableK1(),
false
])
.then(() => {
[this.peserta, this.penilaian1, this.subkriteria, this.kriteria]
})
.catch(function (error) {
console.log(error);
});
},
loadPeserta: function () {
axios.get('http://127.0.0.1:8000/api/penilaian1/peserta1', {
params: this.selected
})
.then((response) => {
this.peserta = response.data.data;
})
.catch(function (error) {
console.log(error);
});
},
loadPenilaian1: function () {
axios.get('http://127.0.0.1:8000/api/penilaian1', {
params: this.selected
})
.then((response) => {
this.penilaian1 = response.data.data;
})
.catch(function (error) {
console.log(error);
});
},
loadTableSK1: function () {
axios.get('http://127.0.0.1:8000/api/penilaian1/table_sk1', {
params: this.selected
})
.then((response) => {
this.subkriteria = response.data.data;
this.loading = false;
})
.catch(function (error) {
console.log(error);
});
},
loadTableK1: function () {
axios.get('http://127.0.0.1:8000/api/penilaian1/table_k1', {
params: this.selected
})
.then((response) => {
this.kriteria = response.data.data;
this.loading = false;
})
.catch(function (error) {
console.log(error);
});
},
}
}
</script>
但预期的结果是这样的:https://i.stack.imgur.com/SgaQo.png
图片显示所有10个nilai被转置到列,但我想基于NIM只转置5个nilai(应该使用groupBy但我不知道)。
那么我如何使用 VueJS 将这个 JSON 数据从行转换到列?就像我的目标一样,提前致谢。
编辑:
我尝试了 Nikola 的 Composition API 和 Axios 解决方案,但没有显示数据:
import axios from 'axios'
import { onMounted, ref, computed } from 'vue'
import SideBar from './../../../components/SideBar.vue'
export default {
components: {
SideBar,
},
setup() {
let peserta1 = ref([])
let result = ref([])
let penilaian1 = ref([])
let subkriteria = ref([])
onMounted(() => {
axios
.get('http://127.0.0.1:8000/api/penilaian1')
.then((result) => {
penilaian1.value = result.data
})
.catch((err) => {
console.log(err.response)
})
})
onMounted(() => {
axios
.get('http://127.0.0.1:8000/api/penilaian1/table_sk1')
.then((result) => {
subkriteria.value = result.data
})
.catch((err) => {
console.log(err.response)
})
})
onMounted(() => {
axios
.get('http://127.0.0.1:8000/api/penilaian1/peserta1')
.then((result) => {
peserta1.value = result.data
})
.catch((err) => {
console.log(err.response)
})
})
const transpose = () => {
penilaian1.value.forEach((dat) => {
if (!result.value.find((r) => r.nim === dat.nim)) {
result.value.push({ nim: dat.nim, nama: dat.nama })
}
})
penilaian1.value.forEach((dat) => {
let res = result.value.find((r) => r.nim === dat.nim)
res[dat.id_sk1] = dat.nilai
})
console.log(result)
}
return {
peserta1,
penilaian1,
subkriteria,
transpose,
}
},
}
<template>
<div class="relative min-h-screen md:flex">
<SideBar />
<div class="flex-1">
<div class="col-12">
<h1 class="px-6 py-6 mb-6 text-3xl font-extrabold">
Data Pendaftar
</h1>
</div>
<div class="col-12">
<div class="flex-1">
<div class="overflow-y-auto sm:-mx-6 lg:-mx-8">
<div class="py-2 inline-clip sm:px-6 lg:px-12">
<div class="overflow-hidden shadow-md sm:rounded-lg">
<table class="min-w-full">
<thead class="bg-gray-100 dark:bg-gray-700">
<tr>
<th
scope="col"
class="px-6 py-3 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400"
>
NIM
</th>
<th
scope="col"
class="px-6 py-3 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400"
>
Nama
</th>
<th
scope="col"
class="relative px-6 py-3"
>
<span class="sr-only"
>Edit</span
>
</th>
</tr>
</thead>
<tbody>
<!-- Product 1 -->
<tr
v-for="peserta1 in transpose"
class="bg-white border-b dark:bg-gray-800 dark:border-gray-600"
>
<td
class="px-6 py-4 text-sm font-medium text-gray-900 whitespace-nowrap dark:text-white"
>
{{ peserta1.nim }}
</td>
<td
class="px-6 py-4 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400"
>
{{ peserta1.nama }}
</td>
<td
class="px-6 py-4 text-sm font-medium text-right whitespace-nowrap"
></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
更新 2,代码现在可以使用 watchEffect 运行:
watchEffect(() => {
state.penilaian1.forEach((dat) => {
if (!state.result.find((r) => r.nim === dat.nim)) {
state.result.push({ nim: dat.nim, nama: dat.nama })
}
})
state.penilaian1.forEach((dat) => {
let res = state.result.find((r) => r.nim === dat.nim)
res[dat.id_sk1] = dat.nilai
})
console.log(state.result)
})
结果如下:
Overall result
Detailed console.log result
现在我会想办法用v-for调用成绩数据,但让我在下一个问题中回答
尝试如下:
const data = [
{"nim":1810112048,"nama":"Annisa indra","id_sk1":11,"nilai":30},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":12,"nilai":30},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":13,"nilai":25},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":21,"nilai":72},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":31,"nilai":57},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":11,"nilai":20},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":12,"nilai":20},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":13,"nilai":10},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":21,"nilai":75},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":31,"nilai":57}
]
const result = [];
data.forEach(dat => {
if(!result.find(r => r.nim === dat.nim)) {
result.push({"nim":dat.nim, "nama": dat.nama})
}
});
data.forEach(dat => {
let res = result.find(r => r.nim === dat.nim)
res[dat.id_sk1] = dat.nilai
});
console.log(result)
所以我有 JSON 来自 Laravel API 的数据(由 Axios 调用),我想转置这些数据:
{"message":"Data peserta tahap 1 OR XI","data":[
{"nim":1810112048,"nama":"Annisa indra","id_sk1":11,"nilai":30},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":12,"nilai":30},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":13,"nilai":25},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":21,"nilai":72},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":31,"nilai":57},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":11,"nilai":20},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":12,"nilai":20},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":13,"nilai":10},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":21,"nilai":75},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":31,"nilai":57}
]}
这是我的目标:
+------------+------------------------+----+----+----+----+----+
| nim | nama | 11 | 12 | 13 | 21 | 31 |
+------------+------------------------+----+----+----+----+----+
| 1810112048 | Annisa indra | 30 | 30 | 25 | 72 | 57 |
| 1810522038 | Muhammad fakhri naufal | 20 | 20 | 10 | 75 | 57 |
+------------+------------------------+----+----+----+----+----+
这是我的 VueJS 视图代码:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<table class="table">
<thead>
<tr>
<th>NIM</th>
<th>Nama</th>
<th v-for="sk in subkriteria" :key="sk.id_sk1">
{{ sk.sub_kriteria }}</th>
</tr>
</thead>
<tbody>
<template v-if="peserta.array != 0">
<tr v-for="(peserta, index) in penilaian1" :key="index">
<td>{{ peserta.nim }}</td>
<td>{{ peserta.nama }}</td>
<template v-if="peserta.array != penilaian1.array ">
<td v-for="sk in subkriteria" :key="sk.id_sk1">
<i>Tidak ada data</i>
</td>
</template>
<template v-else>
<td v-for="penilaian in penilaian1" :key="penilaian.id_sk1">
{{ penilaian.nilai }}
</td>
</template>
<td>
<div class="btn-group">
<router-link
:to="{ name: 'penilaian1.show', params:{id: penilaian1.id}}"
class="btn btn-sm btn-outline-info">Show</router-link>
</div>
</td>
</tr>
</template>
</tbody>
</table>
<script>
import axios from 'axios'
export default {
computed:{
countedMhs: function() {
return this.peserta.filter(penilaian1 => penilaian1.nim==0);
},
rolesByCategory() {
return _.groupBy(this.penilaian1.nim )
}
},
data: function () {
return {
peserta: [],
penilaian1: [],
subkriteria: [],
kriteria: [],
loading: true,
}
},
mounted() {
this.loadData();
},
watch: {
selected: {
handler: function () {
this.loadData();
},
deep: true
}
},
methods: {
loadData: function () {
this.loading = true;
Promise.all([
this.loadPeserta(),
this.loadPenilaian1(),
this.loadTableSK1(),
this.loadTableK1(),
false
])
.then(() => {
[this.peserta, this.penilaian1, this.subkriteria, this.kriteria]
})
.catch(function (error) {
console.log(error);
});
},
loadPeserta: function () {
axios.get('http://127.0.0.1:8000/api/penilaian1/peserta1', {
params: this.selected
})
.then((response) => {
this.peserta = response.data.data;
})
.catch(function (error) {
console.log(error);
});
},
loadPenilaian1: function () {
axios.get('http://127.0.0.1:8000/api/penilaian1', {
params: this.selected
})
.then((response) => {
this.penilaian1 = response.data.data;
})
.catch(function (error) {
console.log(error);
});
},
loadTableSK1: function () {
axios.get('http://127.0.0.1:8000/api/penilaian1/table_sk1', {
params: this.selected
})
.then((response) => {
this.subkriteria = response.data.data;
this.loading = false;
})
.catch(function (error) {
console.log(error);
});
},
loadTableK1: function () {
axios.get('http://127.0.0.1:8000/api/penilaian1/table_k1', {
params: this.selected
})
.then((response) => {
this.kriteria = response.data.data;
this.loading = false;
})
.catch(function (error) {
console.log(error);
});
},
}
}
</script>
但预期的结果是这样的:https://i.stack.imgur.com/SgaQo.png
图片显示所有10个nilai被转置到列,但我想基于NIM只转置5个nilai(应该使用groupBy但我不知道)。
那么我如何使用 VueJS 将这个 JSON 数据从行转换到列?就像我的目标一样,提前致谢。
编辑: 我尝试了 Nikola 的 Composition API 和 Axios 解决方案,但没有显示数据:
import axios from 'axios'
import { onMounted, ref, computed } from 'vue'
import SideBar from './../../../components/SideBar.vue'
export default {
components: {
SideBar,
},
setup() {
let peserta1 = ref([])
let result = ref([])
let penilaian1 = ref([])
let subkriteria = ref([])
onMounted(() => {
axios
.get('http://127.0.0.1:8000/api/penilaian1')
.then((result) => {
penilaian1.value = result.data
})
.catch((err) => {
console.log(err.response)
})
})
onMounted(() => {
axios
.get('http://127.0.0.1:8000/api/penilaian1/table_sk1')
.then((result) => {
subkriteria.value = result.data
})
.catch((err) => {
console.log(err.response)
})
})
onMounted(() => {
axios
.get('http://127.0.0.1:8000/api/penilaian1/peserta1')
.then((result) => {
peserta1.value = result.data
})
.catch((err) => {
console.log(err.response)
})
})
const transpose = () => {
penilaian1.value.forEach((dat) => {
if (!result.value.find((r) => r.nim === dat.nim)) {
result.value.push({ nim: dat.nim, nama: dat.nama })
}
})
penilaian1.value.forEach((dat) => {
let res = result.value.find((r) => r.nim === dat.nim)
res[dat.id_sk1] = dat.nilai
})
console.log(result)
}
return {
peserta1,
penilaian1,
subkriteria,
transpose,
}
},
}
<template>
<div class="relative min-h-screen md:flex">
<SideBar />
<div class="flex-1">
<div class="col-12">
<h1 class="px-6 py-6 mb-6 text-3xl font-extrabold">
Data Pendaftar
</h1>
</div>
<div class="col-12">
<div class="flex-1">
<div class="overflow-y-auto sm:-mx-6 lg:-mx-8">
<div class="py-2 inline-clip sm:px-6 lg:px-12">
<div class="overflow-hidden shadow-md sm:rounded-lg">
<table class="min-w-full">
<thead class="bg-gray-100 dark:bg-gray-700">
<tr>
<th
scope="col"
class="px-6 py-3 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400"
>
NIM
</th>
<th
scope="col"
class="px-6 py-3 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400"
>
Nama
</th>
<th
scope="col"
class="relative px-6 py-3"
>
<span class="sr-only"
>Edit</span
>
</th>
</tr>
</thead>
<tbody>
<!-- Product 1 -->
<tr
v-for="peserta1 in transpose"
class="bg-white border-b dark:bg-gray-800 dark:border-gray-600"
>
<td
class="px-6 py-4 text-sm font-medium text-gray-900 whitespace-nowrap dark:text-white"
>
{{ peserta1.nim }}
</td>
<td
class="px-6 py-4 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400"
>
{{ peserta1.nama }}
</td>
<td
class="px-6 py-4 text-sm font-medium text-right whitespace-nowrap"
></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
更新 2,代码现在可以使用 watchEffect 运行:
watchEffect(() => {
state.penilaian1.forEach((dat) => {
if (!state.result.find((r) => r.nim === dat.nim)) {
state.result.push({ nim: dat.nim, nama: dat.nama })
}
})
state.penilaian1.forEach((dat) => {
let res = state.result.find((r) => r.nim === dat.nim)
res[dat.id_sk1] = dat.nilai
})
console.log(state.result)
})
结果如下: Overall result Detailed console.log result
现在我会想办法用v-for调用成绩数据,但让我在下一个问题中回答
尝试如下:
const data = [
{"nim":1810112048,"nama":"Annisa indra","id_sk1":11,"nilai":30},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":12,"nilai":30},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":13,"nilai":25},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":21,"nilai":72},
{"nim":1810112048,"nama":"Annisa indra","id_sk1":31,"nilai":57},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":11,"nilai":20},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":12,"nilai":20},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":13,"nilai":10},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":21,"nilai":75},
{"nim":1810522038,"nama":"Muhammad fakhri naufal","id_sk1":31,"nilai":57}
]
const result = [];
data.forEach(dat => {
if(!result.find(r => r.nim === dat.nim)) {
result.push({"nim":dat.nim, "nama": dat.nama})
}
});
data.forEach(dat => {
let res = result.find(r => r.nim === dat.nim)
res[dat.id_sk1] = dat.nilai
});
console.log(result)