Hi @KwebenaAcquah-9104,
Your shared code is not enough to reproduce your issue. Any way, here is a whole working demo you could follow which is based on Blazor Server App:
Razor Component
@page "/productmodal"
@rendermode InteractiveServer
@inject IJSRuntime JS
<button @onclick="OpenModal" class="btn btn-primary">Open Modal</button>
@if (selectedProduct != null)
{
<div id="productModal" class="modal d-block" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content shadow-lg">
<!-- Header -->
<div class="modal-header" style="text-align: center;">
<h5 class="modal-title">@CurrentProduct.Name</h5>
<button type="button" class="close-btn" @onclick="CloseModal" style="font-size: 0.8rem; padding: 5px 10px;">X</button>
</div>
<!-- Body -->
<div class="modal-body position-relative">
<!-- Navigation Buttons -->
<button class="nav-btn left-btn" @onclick="PreviousSubCategory" style="position: absolute; left: 10px; top: 40%; transform: translateY(-50%);"><</button>
<img src="@CurrentProduct.ImageUrl" alt="@CurrentProduct.Name" class="img-fluid mb-3 modal-image" style="display: block; margin: auto;">
<button class="nav-btn right-btn" @onclick="NextSubCategory" style="position: absolute; right: 10px; top: 40%; transform: translateY(-50%);">></button>
<!-- Details -->
<div>
<p><strong>Description:</strong> @CurrentProduct.Description</p>
<p><strong>Price:</strong> GHS @CurrentProduct.Price</p>
<p><strong>Rating:</strong> ⭐️ @CurrentProduct.Rating / 5</p>
</div>
</div>
<!-- Footer -->
<div class="modal-footer">
<button class="btn btn-primary" onclick="OpenOrderPopup()">Place Order</button>
</div>
</div>
</div>
</div>
}
@code {
private Dictionary<string, ProductSliderState> productSliderStates;
private Product selectedProduct;
private string productCategoryKey = "Phones";
protected override async Task OnInitializedAsync()
{
// Sample data
productSliderStates = new Dictionary<string, ProductSliderState>
{
["Phones"] = new ProductSliderState
{
currentIndex = 0,
sliderProducts = new List<Product>
{
new Product { Name = "Phone A", Description = "Description A", Price = 1000, Rating = 4.5, ImageUrl = "images/phoneA.png" },
new Product { Name = "Phone B", Description = "Description B", Price = 1200, Rating = 4.7, ImageUrl = "images/phoneB.png" },
new Product { Name = "Phone C", Description = "Description C", Price = 900, Rating = 4.0, ImageUrl = "images/phoneC.png" }
}
}
};
selectedProduct = productSliderStates[productCategoryKey].sliderProducts[0];
}
private async Task OpenModal()
{
var images = productSliderStates[productCategoryKey].sliderProducts.Select(p => p.ImageUrl).ToList();
await JS.InvokeVoidAsync("openProductModal", images); // Awaited to ensure correct initialization
}
private async Task CloseModal()
{
await JS.InvokeVoidAsync("closeProductModal");
}
private async Task PreviousSubCategory()
{
var state = productSliderStates[productCategoryKey];
state.currentIndex = (state.currentIndex - 1 + state.sliderProducts.Count) % state.sliderProducts.Count;
selectedProduct = state.sliderProducts[state.currentIndex];
// Sync with JS
await JS.InvokeVoidAsync("updateModalImage", selectedProduct.ImageUrl);
}
private async Task NextSubCategory()
{
var state = productSliderStates[productCategoryKey];
state.currentIndex = (state.currentIndex + 1) % state.sliderProducts.Count;
selectedProduct = state.sliderProducts[state.currentIndex];
// Sync with JS
await JS.InvokeVoidAsync("updateModalImage", selectedProduct.ImageUrl);
}
private Product CurrentProduct => productSliderStates[productCategoryKey].sliderProducts[productSliderStates[productCategoryKey].currentIndex];
private class Product
{
public string Name { get; set; }
public string Description { get; set; }
public double Price { get; set; }
public double Rating { get; set; }
public string ImageUrl { get; set; }
}
private class ProductSliderState
{
public int currentIndex { get; set; }
public List<Product> sliderProducts { get; set; }
}
}
JS
let images = [];
let currentIndex = 0;
let modalImageInterval;
function openProductModal(imageUrls) {
images = imageUrls;
currentIndex = 0;
updateModalImage();
document.getElementById('productModal').style.display = 'block';
// Start Auto-Cycling
startModalImageSlider();
}
// Dynamically update modal image
function updateModalImage(imageUrl) {
if (imageUrl) {
document.querySelector('.modal-image').src = imageUrl;
} else {
document.querySelector('.modal-image').src = images[currentIndex];
}
}
// Start Automatic Cycling
function startModalImageSlider() {
stopModalImageSlider(); // Ensure no duplicate intervals
modalImageInterval = setInterval(() => {
currentIndex = (currentIndex + 1) % images.length;
updateModalImage();
}, 60000); // Every 60 seconds
}
// Stop Automatic Cycling
function stopModalImageSlider() {
clearInterval(modalImageInterval);
}
// Close Modal
function closeProductModal() {
stopModalImageSlider();
document.getElementById('productModal').style.display = 'none';
}
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
Best regards,
Rena