1
votes

I have a sample json that I need to parse and visualize as a table in a RShiny app. My json is as below

{
    "line1": [
      {
        "model": "Cooper",
        "year": 2018,
        "type": "Hatchback",
        "motorization": "Electric",
        "colour": "Midnight Black",
        "stageID": "MGOP94810482042"
      },
      {
        "model": "BMW",
        "year": 2020,
        "type": "Hatchback",
        "motorization": "Electric",
        "colour": "Eccentric blue",
        "stageID": "M5"
      }
    ],
    "line2": [
      {
        "model": "Cooper",
        "year": 2018,
        "type": "Hatchback",
        "motorization": "Diesel",
        "colour": "Silver",
        "stageID": "MGOP9183740194"
      }
    ]
}

I use jsonlite package to convert this data into dataframes and dynamically render the tables without hardcoding them. Here goes my code.

library(shiny)
library(jsonlite)
library(DT)
library(data.table)

rawJsonData <- fromJSON("Test.json")

ui <- fluidPage(
  h1("My app"),
  br(),
  tags$div(id = "jsontables")
)

server <- function(input, output, session) {

  observe({

    for(i in 1:length(rawJsonData)){
      if(class(rawJsonData[[i]])=="data.frame"){
        tid <- paste0("dt", i)
        tabledata <- rawJsonData[[i]]
        
        insertUI(
            selector = "#jsontables",
            ui = tags$div(
                          DT::dataTableOutput(tid),
                          hr()
            )
          )
        

        output[[tid]] <- DT::renderDataTable(server = FALSE,{
          DT::datatable(tabledata)
        })
        
      }
      
    }
  })
}

shinyApp(ui = ui, server = server)

The app seems to work fine, but in both the tables rendered, I see the dataframe corresponding to 'line2' is getting inserted.

enter image description here

I tried to understand where the issue is and I see that when the loop runs for the second time, when the line tabledata <- rawJsonData[[i]] executes, it overwrites the first table in the UI. When I stop the code execution by adding return() after the loop runs for the first time, I am able to see my first table properly.

enter image description here

Not sure why this happens. Any help is much appreciated!

1

1 Answers

1
votes

This works by using local. And you don't need an observer.

library(shiny)
library(DT)

rawJsonData <- list(iris[1:4,], mtcars[1:4,])

ui <- fluidPage(
  h1("My app"),
  br(),
  tags$div(id = "jsontables")
)

server <- function(input, output, session) {
  
  for(i in 1:length(rawJsonData)){
    if(class(rawJsonData[[i]])=="data.frame"){
      tid <- paste0("dt", i)
      
      local({
        
        tabledata <- rawJsonData[[i]]
        id <- tid
        
        insertUI(
          selector = "#jsontables",
          ui = tags$div(
            DTOutput(id),
            hr()
          )
        )
        
        output[[id]] <- renderDT(server = FALSE, {
          datatable(tabledata)
        })
        
      })
      
    }
    
  }
  
}

shinyApp(ui = ui, server = server)