Hi,
I am trying to create an interactive UMAP in my HTML that I get after knitting my RMarkdown. I am trying to avoid using RShiny since I have no where to host the app, and need to share multiple analysis to different people. The issue I am facing right now is that everything loads but the text box is not interactive. Nothing happens after I enter a gene name and I do not have enough javascript/interactive experience to debug this issue. Would appreciate any help!
```{r, echo=FALSE, message=FALSE, warning=FALSE}
library(Seurat)
library(ggplot2)
library(plotly)
library(htmltools)
# Extract UMAP coordinates
umap_df <- as.data.frame(Embeddings(seurat_obj, reduction = "umap"))
colnames(umap_df) <- c("UMAP_1", "UMAP_2")
# Function to plot UMAP dynamically
plot_umap <- function(gene) {
gene <- toupper(gene) # Ensure case-insensitive matching
if (!(gene %in% rownames(seurat_obj))) {
return(ggplot() + ggtitle("Gene not found") + theme_void()) # Show message if gene doesn't exist
}
umap_df$Expression <- FetchData(seurat_obj, vars = gene)[,1]
p <- ggplot(umap_df, aes(x = UMAP_1, y = UMAP_2, color = Expression)) +
geom_point() +
scale_color_gradient(low = "lightgray", high = "red") +
theme_minimal() +
ggtitle(paste("UMAP Expression:", gene))
ggplotly(p)
}
# Load initial gene (random)
set.seed(123)
default_gene <- sample(rownames(seurat_obj), 1)
plotly_plot <- plot_umap(default_gene)
# JavaScript for real-time text input update
js_code <- HTML("
<script>
function updateGene() {
var gene = document.getElementById('geneInput').value.toUpperCase();
Shiny.setInputValue('selected_gene', gene);
}
</script>
")
# Create text box input
text_input <- HTML('
<div style="margin-bottom: 10px;">
<label for="geneInput"><strong>Search Gene:</strong></label>
<input type="text" id="geneInput" oninput="updateGene()" placeholder="Enter gene name">
</div>
')
# Embed text box + JS
htmlwidgets::prependContent(
plotly_plot,
tags$div(text_input, js_code)
)
```
HTML output: