I have some bootstrap-vue tables that I use to dynamically display information for some items parsed from JSON. The fields the table will hold are static, and I'm trying to get images to display in one column of the table. All of the images are contained within the project locally. What I would like to have happen is for every item parsed and displayed in the table, a string containing the src path to the correct image will be calculated, and that the correct image for each item will be displayed for each object in the table.
Currently instead of an image showing in the table, a placeholder string "[object HTMLImageElement]" shows instead. I've looked into many questions and answers on StackOverflow pertaining to that text being shown instead of an image, but the posts I've seen relate to static webpages with fixed image sources that don't change.
While parsing items from JSON, I save relevant information and create item objects that are pushed into an items array, which is then displayed in the table. When viewing the console logs I'm about 90% sure the dynamic path to each image is being created properly, and for each GET request that is made when fetching the image resource, I get a 304 Not Modified response.
For reference, the item images are stored in my project with the following file structure: src/assets/items-icons/itemIdHere.png
Below are the functions I use and an example vue component where I build the use the functions to build a table.
/**
* Use Axios to request and save the latest item summary from the OSBuddy API.
* Uses the apiUrl const declared above and saves the results in itemSummary.
*/
export function generateTable (theItemSummary, theItemIdList, theItems) {
console.log('Fetching the latest summary.')
axios.get(apiUrl)
.then(response => {
console.log('Retrieved the latest item summary.')
theItemSummary = JSON.parse(JSON.stringify(response.data))
parseItems(theItemSummary, theItemIdList, theItems)
})
.catch(error => {
console.log('Error getting the latest summary: ' + error)
})
}
/**
* Helper function for generateTable(). Takes the entire item summary and attempts
* to save the desired values from each nested object, then saves the results inside
* the items array for display in the table.
*/
export function parseItems (theItemSummary, theItemIdList, theItems) {
const imagePrefix = '../../assets/items-icons/'
const imageSuffix = '.png'
if (theItemSummary) {
let currItem // Current item from the itemIDList.
for (let i = 0; i < Object.keys(theItemSummary).length; i++) {
let computedItem = {}
currItem = theItemIdList[i]
// Get the up to date info from the item summary for each particular item.
computedItem.itemName = theItemSummary[currItem].name
// Save the item icon as a property of the computed item.
let itemImage = new Image()
itemImage.src = imagePrefix + String(theItemSummary[currItem].id) + imageSuffix
computedItem.itemIcon = itemImage
// Find the buying value of the current item. Inactive prices are left undefined.
if (theItemSummary[currItem].buy_average.valueOf() === 0) {
computedItem.buyPrice = 'Inactive'
} else {
computedItem.buyPrice = theItemSummary[currItem].buy_average
}
// Find the selling value of the current item. Inactive prices are left undefined.
if (theItemSummary[currItem].sell_average.valueOf() === 0) {
computedItem.sellPrice = 'Inactive'
} else {
computedItem.sellPrice = theItemSummary[currItem].sell_average
}
// Calculate the margin of the item. Leave it undefined if either prices are inactive.
if (computedItem.buyPrice === 'Inactive' || computedItem.sellPrice === 'Inactive') {
computedItem.margin = 'Unknown'
} else {
computedItem.margin = computedItem.sellPrice - computedItem.buyPrice
}
if (String(theItemSummary[currItem].members).includes('true')) computedItem.isMembers = 'Members'
else computedItem.isMembers = 'Free to Play'
// Store the item into the items list.
theItems.push(computedItem)
}
console.log('Successfully parsed the item summary.')
} else {
console.log('Error: Attempted to parse undefined item summary.')
}
}
Here is Vue component example:
<template>
<b-container>
<div id="header">
<header>Fish</header>
</div>
<div id="table">
<b-table
striped
dark
:items="items"
:fields="fields">
</b-table>
</div>
</b-container>
</template>
<script>
import * as table from '../../tableFunctions'
const fishIdList = [ 317, 315, 327, 325, 345, 347, 321, 319, 353, 355, 335, 333, 341, 339, 349,
351, 331, 329, 359, 361, 10138, 10136, 5001, 5003, 377, 379, 363, 365, 371, 373, 7944,
7946, 3142, 3144, 383, 385, 395, 397, 389, 391, 13439, 13441, 11934, 11936 ]
export default {
data () {
return {
// The summary generated and retrieved from the OSBuddy API.
itemSummary: undefined,
// Array containing the item ID of every item we want to display in the table.
itemIdList: fishIdList,
// List of all items accessed from the itemSummary, meant to display in table.
items: [],
// Fields for use at the table header.
fields: {
itemIcon: {
sortable: false
},
itemName: {
label: 'Item Name',
sortable: true
},
buyPrice: {
label: 'Buy Price',
sortable: true
},
sellPrice: {
label: 'Sell Price',
sortable: true
},
margin: {
label: 'Margin',
sortable: true
},
isMembers: {
label: 'Members Item',
sortable: true
}
}
}
},
mounted () {
table.generateTable(this.itemSummary, this.itemIdList, this.items)
}
}
</script>
<style scoped>
header {
font-size: 32px;
}
table {
color: whitesmoke;
font-size: 18px;
}
</style>
Finally, if it helps describe my issue at all, here is a link to the table in it's current state and how it is appearing.