In my Vue3 component, I created a feature to showcase data using chips. The input is an Object with keys as indexes and values containing the element to be displayed.
Here is the complete code documentation:
<template>
<div class="row">
<div>a fixed entry during debug</div>
<q-chip v-for="alert in failedAlerts" :key="alert.Id" color="orange">{{ alert.FullTargetName }}</q-chip>
</div>
</template>
<script lang="ts">
import {toRef, Ref, computed, watch} from 'vue'
import log from 'assets/log'
interface Alert {
IsOK: boolean;
FullTargetName: string,
Why: string,
Extra: string,
Id: string,
When: string
}
function alertFactory(): Alert {
return {
Extra: '', FullTargetName: 'dummy alert', Id: '0', IsOK: false, When: '0', Why: 'dummy alert explanation',
}
}
export default {
name: 'Homemonitor',
// the complete props definitiin is temporarily commented out to make sure the problem
// does not come from here
// props: {
// alerts: {
// type: Object,
// default: () => alertFactory(),
// },
// },
props: ['alerts'],
setup(props) {
// TODO: review the global eslint exclusions below
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
let failedAlerts = computed(() => Object.values(toRef(props, 'alerts')).filter((x: Alert) => !x.IsOK))
return {failedAlerts}
},
}
</script>
<style scoped>
</style>
Upon inspecting DevTools → Vue, I noticed that failedAlerts
wasn't the expected neat Array of Alert
, but rather
alert
in both props and
setup → failedAlerts → alerts` contains the correct content
The issue arises because Object.values()
should have returned an Array of values from the object (filtered).
Based on the provided data, it should look something like this: (IsOK
being true
would filter it out)
// failedAlerts
[
{
"IsOK":true,
"FullTargetName":"bind → Amazon_Fire",
"Why":"",
"Extra":"",
"Id":"8bd3b2c7fe73ea6c0d0aac324baaa354",
"When":"2021-08-19T13:02:33+02:00"
},
(...)
]
What could be causing failedAlerts
to have the current structure?
UPDATE: After carefully examining the types in my code (thanks to @EstusFlask for the help), I believe I have resolved the issues in the <script>
section.
<script lang="ts">
import {computed, Ref, toRef, watch} from 'vue'
interface Alert {
IsOK: boolean;
FullTargetName: string,
Why: string,
Extra: string,
Id: string,
When: string
}
function alertFactory(): Record<string, Alert> {
return {
'dummy index':
{
Extra: '', FullTargetName: 'dummy alert', Id: '0', IsOK: false, When: '0', Why: 'dummy alert explanation',
},
}
}
export default {
name: 'Homemonitor',
props: {
alerts: {
type: Object,
required: true,
// default: () => alertFactory(),
},
},
// props: ['alerts'],
setup(props) {
// TODO: review the global eslint exclusions below
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
let failedAlerts = computed(() => Object.values(props.alerts as Ref<Record<string, Alert>>).filter((x: Alert) => !x.IsOK))
return {failedAlerts}
},
}
</script>