Display uploaded image when specific NFT card is selected in image carousel

I’m building an NFT gallery carousel and need help with image handling. When users upload a picture through a file input, I want to store it (preferably in localStorage or cookies without using backend languages) and display it only when that specific NFT card is active in the slider.

const backButton = document.querySelector("#back-btn");
const forwardButton = document.querySelector("#forward-btn");
let tokenTitle = document.querySelector("#title");
let tokenInfo = document.querySelector("#info");
let tokenValue = document.querySelector(".price");
let tokenDuration = document.querySelector("#duration");
let tokenArtist = document.querySelector("span");
let collection = [];
let activeToken;

let submitForm = document.querySelector(".form-submit");
let inputTitle = document.querySelector("#input-title");
let inputInfo = document.querySelector("#info-input");
let inputValue = document.querySelector("#value-input");
let inputDuration = document.querySelector("#duration-input");
let inputArtist = document.querySelector("#artist-input");

let chosenFile;
let imageToggle = document.getElementById("image-selector");
let imageDisplay = document.querySelector(".token-image");
let fileInput = document.createElement("input");
fileInput.setAttribute("type", "file");
fileInput.setAttribute("accept", "image/*");

class TokenCard {
    constructor(id, title, info, value, duration, artist, picture) {
        this.id = id;
        this.title = title;
        this.info = info;
        this.value = value;
        this.duration = duration;
        this.artist = artist;
        this.pictureData = picture;
    }
}

let currentIndex = 0;
collection = [];

let addNewToken = function () {
    chosenFile = fileInput.files[0];
    let fileReader = new FileReader();
    fileReader.addEventListener("load", function () {
        imageDisplay.src = fileReader.result;
    }, false);

    if (chosenFile) {
        fileReader.readAsDataURL(chosenFile);
    }

    let newToken = new TokenCard(
        collection.length,
        inputTitle.value,
        inputInfo.value,
        inputValue.value + "eth",
        inputDuration.value,
        inputArtist.value,
        collection.length
    );

    collection.push(newToken);
    
    inputTitle.value = "";
    inputInfo.value = "";
    inputValue.value = "";
    inputDuration.value = "";
    inputArtist.value = "";
};

let displayCurrentToken = function () {
    activeToken = collection[currentIndex];
    tokenTitle.textContent = activeToken.title;
    tokenInfo.textContent = activeToken.info;
    tokenValue.textContent = activeToken.value;
    tokenDuration.textContent = activeToken.duration;
    tokenArtist.textContent = activeToken.artist;
    imageDisplay.src = activeToken.pictureData;
};

The main issue is properly linking uploaded images to their corresponding NFT cards and displaying the correct image when navigating through the carousel.

Cool project! Quick question though - have you thought about localStorage size limits? Base64 images can get huge and localStorage caps out around 5-10MB depending on the browser.

I’m a bit confused about your flow. When addNewToken() runs, are you immediately reading and displaying the file? I see you’re setting imageDisplay.src = fileReader.result in that function, but then displayCurrentToken() tries to set it again with activeToken.pictureData.

I think you need to store the fileReader.result in the TokenCard when you create it. Maybe save the base64 string as the pictureData property instead of just the collection length?

How do your navigation buttons work? Do they call displayCurrentToken() when users click forward/back? I’d love to see that part since that’s probably where the image switching needs to happen.

you’re storing the file data wrong - pictureData needs the actual base64 string from fileReader.result, not the collection length. save fileReader.result to a variable first, then pass that to the TokenCard constructor instead of collection.length

Your issue is with the image data flow. FileReader runs asynchronously, but you’re creating TokenCard right after starting the file read. So pictureData ends up being collection.length instead of the actual image data.

Put the TokenCard creation inside FileReader’s load event handler. Store the base64 string in localStorage with a unique key for each token - localStorage.setItem('nft_image_' + tokenId, fileReader.result). Then in displayCurrentToken(), grab it with localStorage.getItem('nft_image_' + activeToken.id). I’ve hit similar carousel problems before - you need to make sure data persistence happens after the file finishes processing, not before.