1

I load a list of items from the db which are to be displayed to the user in a list. Each item is of a particular type, and depending on the type, I wish to show an icon next to it.

I've created a component to control the icon that will be shown. The component accepts the type sa a prop and renders the mdi-icon accordingly.

<div v-if="iconName !== ''">
  <v-icon large color="blue-grey darken-2"> 
    {{ iconName }}
  </v-icon> 
  </div>

The value of iconName is provided either while mounting, or as a computed property - I tried both of these.

export default {
  props: ["activityType"],

  data() {
    return {
      iconType: this.activityType, 
      iconName: 'mdi-script-text-outline', 
      iconMapping: {
        learning_material_video: "mdi-video",
        learning_material_quiz: "mdi-head-question-outline",
        learning_material_article: "mdi-script-text-outline",
      },
    };
  },
  methods: {},
  mounted(){
    this.iconName = this.iconMapping[this.iconType]
  },
  computed: {
    // iconName() {
    //   return this.iconMapping[this.activityType]
    // },
  },
};

This renders perfectly fine and I can ignore and continue working on the next component but the error in the console is a bit worrysome.

Uncaught (in promise) Error: Icon value is undefined or null
at ReactiveEffect.eval [as fn] (icons.tsx?ff78:168:1)
at ReactiveEffect.run (reactivity.esm-bundler.js?89dc:167:1)
at ComputedRefImpl.get value [as value] (reactivity.esm-bundler.js?89dc:1101:1)
at Proxy.eval (VIcon.tsx?e5c2:53:1)
at renderComponentRoot (runtime-core.esm-bundler.js?d2dd:893:1)
at ReactiveEffect.componentUpdateFn [as fn] (runtime-core.esm-bundler.js?d2dd:5098:1)
at ReactiveEffect.run (reactivity.esm-bundler.js?89dc:167:1)
at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:155:1)
at flushJobs (runtime-core.esm-bundler.js?d2dd:394:1)
at flushJobs (runtime-core.esm-bundler.js?d2dd:409:1)

This has no effect in how the page looks or works but I'm worried if this might create issues later. I'm hardly 5 days in into Vue and I might be doing something wrong here. Is my code the right way to do it or can it be better?

ps. This is Vuetify-3.

Aditya
  • 3,080
  • 24
  • 47
  • You can try adding `v-if="iconName"` to your `v-icon`. – IVO GELOV Mar 25 '22 at 16:21
  • @IVOGELOV edited the question to show you what I'm already doing. If I add v-if to v-icon instead, the first icon doesn't load (but rest of them do). – Aditya Mar 25 '22 at 16:46
  • @Aditya you used ```v-if="iconName !== ''"``` in your code, but if I am not wrong the ```iconName``` has default value and that condition does not solve the problem. You should post the codes of **parent** component that loads data to get better answers. – hamid-davodi Mar 25 '22 at 19:55

2 Answers2

3

You should use a safety guard:

<template>
  <div>
    <v-icon large color="blue-grey darken-2">{{ iconName }}</v-icon> 
  </div>
</template>

<script>
export default
{
  name: 'MyCustomComponent',
  props:
  {
    activityType:
    {
      type: String,
      default: ''
    }
  },
  computed
  {
    iconName()
    {
      return {
        learning_material_video: "mdi-video",
        learning_material_quiz: "mdi-head-question-outline",
        learning_material_article: "mdi-script-text-outline",
      }[this.activityType] || 'mdi-script-text-outline';
    }
  }
}
IVO GELOV
  • 13,496
  • 1
  • 17
  • 26
1

I load a list of items from the db

I think the issue is somewhere there. The error you're getting basically says that when you fetch the data, something goes wrong but you don't catch it (don't do anything about it). I think in your case you need to catch the error and assign a value to Icon inside the catch block.

Oleg Naumov
  • 545
  • 1
  • 3
  • 10