Home > Software engineering >  How to Display images in vuetify datatable using paths
How to Display images in vuetify datatable using paths

Time:03-17

So I have this array item :

[
  {
    "name": "user language check dates in different language",
    "tag": "@DHRD-52484",
    "status": "passed",
    "refimages": [
      "/captures/ref_01_03_2022_17_05_21/@DHRD-52484/user language check dates in different language/1.png",
      "/captures/ref_01_03_2022_17_05_21/@DHRD-52484/user language check dates in different language/2.png",
      "/captures/ref_01_03_2022_17_05_21/@DHRD-52484/user language check dates in different language/3.png",
      "/captures/ref_01_03_2022_17_05_21/@DHRD-52484/user language check dates in different language/4.png"
    ],
    "testimages": [
      "/captures/test_07_03_2022_10_13_48/@DHRD-52484/user language check dates in different language/1.png",
      "/captures/test_07_03_2022_10_13_48/@DHRD-52484/user language check dates in different language/2.png",
      "/captures/test_07_03_2022_10_13_48/@DHRD-52484/user language check dates in different language/3.png",
      "/captures/test_07_03_2022_10_13_48/@DHRD-52484/user language check dates in different language/4.png"
    ],
    "resultimages": [
      "/VisualTests/test_07_03_2022_10_13_48/@DHRD-52484/user language check dates in different language/1.png",
      "/VisualTests/test_07_03_2022_10_13_48/@DHRD-52484/user language check dates in different language/2.png",
      "/VisualTests/test_07_03_2022_10_13_48/@DHRD-52484/user language check dates in different language/3.png",
      "/VisualTests/test_07_03_2022_10_13_48/@DHRD-52484/user language check dates in different language/4.png"
    ]
  }
]

and I've been trying to have a table using vuetify with each row representing the index of the image,the refimage, testimage and result image this is my code so far :

<template>
  <v-app>
    <app-navbar />

    <v-main>
      <h3>
        test {{ $route.params.name }}, {{ $route.query.status }},{{
          $route.query.tag
        }}
      </h3>
      <h3>{{ imagesref }}</h3>
      <v-data-table
    :headers="headers"
    :items="items"
    :items-per-page="5"
    
  ></v-data-table>

    </v-main>
  </v-app>
</template>

<script>
import appNavbar from "../../../components/appNavbar.vue"
import axios from "axios"
export default {
  components: { appNavbar },
  name: "App",
  data() {
    return {
      items: [],
      imagesref: [],
      imagestest: [],
      imagesresult: [],
      headers: [
        {
          text: "index",
          align: "start",
          sortable: false,
          value: "index",
        },
        { text: "reference image", value: "refimages" },
        { text: "test image", value: "test" },
        { text: "result image", value: "result" },
      ],
    }
  },
  async created() {
    try {
      const res = await axios.get(`http://localhost:3004/tests`, {
        params: { name: this.$route.params.name },
      })
      this.items = res.data
      this.imagesref = res.data[0].refimages
      this.imagestest = res.data[0].testimages
      this.imagesresult = res.data[0].resultimages
    } catch (error) {
      console.log(error)
    }
  },
}
</script>

<style lang="scss" scoped>
</style>

I tried saving the refimages,testimages and resultimages array in 3 variables but I still don't know how can i iterate over these 3 arrays in parallel and use the img tag to display the image from the path

CodePudding user response:

I found a solution for your problem that for better explaining that, I separate it to some steps:

step1: Test the img urls

First of all put an <img> tag to the component to test that the urls you defined in your data actually works or not:

<img width="50" src="../assets/images/1.png">

Here I have 1.png image in my assets directory. If that does not show the image, that means your url address (for example /captures/test_07_03_2022_10_13_48/@DHRD-52484/user language check dates in different language/1.png) have some problem. Try to fix that to continue.

step2: Store data in "json" file

After that if you do not have any problems with your images urls, you must paste your data in a json file that is saved in your public directory. Here I called it dataMe.json and put these sample data on it. you can put your own data:

[
  {
    "name": "user1",
    "tag": "@DHRD-52484-1",
    "status": "passed",
    "imgUrl": "1.png"
  },
  {
    "name": "user2",
    "tag": "@DHRD-52484-2",
    "status": "passed",
    "imgUrl": "2.png"
  },
  {
    "name": "user3",
    "tag": "@DHRD-52484-3",
    "status": "passed",
    "imgUrl": "5.png"
  }
]

At this point, if you paste http://localhost:8080/dataMe.json (instead of 8080, use your own port number) in your browser address bar, you should see the data that is in the file in your browser.

step3: Change your template and script codes

If you want to iterate over your data in vuetify table, you should not separate the data. All the data comes from your axios request must be in items data of your vue component. Here is the code of my component:

<template>
  <v-app>
    
    <v-main>
      <v-data-table
          :headers="headers"
          :items="items"
      >
        <!-- This template is used to have custom html elements in your specific column of the table -->
        <template v-slot:item.imgUrl="{ item }">
          <!-- You can uncomment the line below to see the actual item data. Also you can use 'v-for' or 'v-if' or other vue capabilities, if your item data is more complex.  -->
          
<!--          <span>{{item}}</span>-->
          <img width="50" :src="require(`../assets/images/${item.imgUrl}`)">
        </template>
      </v-data-table>
    </v-main>
  </v-app>
</template>

<script>

import axios from "axios"
export default {
  name: "DataView",
  data() {
    return {
      items: [],
      // imagesref: [],
      // imagestest: [],
      // imagesresult: [],
      headers: [
        { text: "name", value: "name" },
        { text: "tag", value: "tag" },
        { text: "status", value: "status" },
        { text: "image", value: "imgUrl" },
      ],
    }
  },
  async created() {
    try {
      // replace the port number with your own port number
      const res = await axios.get('http://localhost:8080/dataMe.json');
      console.log(res.data);
      this.items = res.data;
      // this.imagesref = res.data[0].refimages
      // this.imagestest = res.data[0].testimages
      // this.imagesresult = res.data[0].resultimages
    } catch (error) {
      console.log(error)
    }
  },
}
</script>

<style scoped>

</style>

As you can see I used v-data-table Slots capability to handle the image problem. With this capability of vuetify you can add or replace custom html elements to built-in vuetify components. Also see this example to better understand the usage of Slots in v-data-table component.

The last tip that I think is necessary to mention is that do not put the whole address of your images in the json data file. Put only the variable part (for example 1.png and 2.png and so on) and for the repeated part (for example /captures/test_07_03_2022_10_13_48/@DHRD-52484/user language check dates in different language) put that in :src="require(... part of your vue template code.

That is the solution that works with my sample data. You may need to add more columns or change your headers or items part of your table to have the desired table that you want with your own data.

CodePudding user response:

Thanks @hamid-davodi for your solution ! I have also tried finding my own and here's what I came up with

    <template>
      <v-app>
               
        <app-navbar />
    
        <v-main>
     
          <h3>
            test {{ $route.params.name }}, {{ $route.query.status }},{{
              $route.query.tag
            }}
          </h3>
          <h3>{{ imagesref }}</h3>
      
            <v-data-table
        :headers="headers"
        :items="imagesref"
        :items-per-page="5"
        
      >
      <template v-slot:[`item.index`]="{ index }">
         
            {{index 1}}
      </template>
      
      <template v-slot:[`item.ref`]="{ index }">
    
            <v-img :src="imagesref[index]" max-width="750" max-height="750" @click="expand"  />
      
      </template>
       <template v-slot:[`item.test`]="{ index }">
         
            <v-img :src="imagestest[index]" max-width="750" max-height="750" />
    
      </template>
         <template v-slot:[`item.res`]="{ index }">
         
            <v-img :src="imagesresult[index]" max-width="750" max-height="750" />
    
      </template>
      </v-data-table>
    
    
        </v-main>
     
      </v-app>
    </template>
    
    <script>
    import appNavbar from "../../../components/appNavbar.vue"
    import axios from "axios"
    export default {
      components: { appNavbar },
      name: "App",
      data() {
        return {
          exp:false,
          items: [],
          imagesref: [],
          imagestest: [],
          imagesresult: [],
                  headers: [
              { text: 'index',value: 'index',sortable:false},
              { text: 'Imagesref', value: 'ref',sortable:false },
              { text: 'Imagestest', value: 'test',sortable:false },
              { text: 'Imagesresult', value: 'res',sortable:false },
              { text: 'Scrubber', value: '',sortable:false },
            ]
        }
      },
      async created() {
        try {
          const res = await axios.get(`http://localhost:3004/tests`, {
            params: { name: this.$route.params.name },
          })
          this.items = res.data
          this.imagesref = res.data[0].refimages
          this.imagestest = res.data[0].testimages
          this.imagesresult = res.data[0].resultimages
        } catch (error) {
          console.log(error)
        }
      },
      methods:{
        expand(){
          this.exp= !this.exp;
    
        }
      }
    }
    </script>
    
    <style  scoped>

    </style>

Since the paths of the images are ordered in the array, I used v-slot with the index object to display each image in the correct row. I'm using nuxtjs so I saved the images in the static folder so that I wouldn't need to change the path.

I hope this can help a fellow beginner in vue/vuetify.

  • Related