Skip to contents

The source for this app can be found here.

Create the column definitions with col_def()

c_def <- list(
  faketables::col_def(
    name = 'Name',
    input = faketables::input_call(
      fun = \(inputId, ...) { shinyjs::disabled(shiny::textInput(inputId, ...)) },
      args = list(label = NULL)
    ),
    cast = as.character,
    width = 2
  ),
  faketables::col_def(
    name = 'Address',
    input = faketables::input_call(
      fun = shiny::textInput,
      args = list(label = NULL)
    ),
    cast = as.character,
    width = 2
  ),
  faketables::col_def(
    name = 'City',
    input = faketables::input_call(
      fun = shiny::selectInput,
      args = list(
        label = NULL,
        choices = c('Bronx', 'Brooklyn', 'New York', 'Queens', 'Staten Island')
      )
    ),
    cast = as.character,
    width = 2
  ),
  faketables::col_def(
    name = 'Zip',
    input = faketables::input_call(
      fun = shiny::numericInput,
      args = list(label = NULL, min = 10001, max = 11697, step = 1)
    ),
    cast = as.integer,
    width = 1
  ),
  faketables::col_def(
    name = 'FavoritePizza',
    input = faketables::input_call(
      fun = shiny::textInput,
      args = list(label = NULL)
    ),
    cast = as.character,
    width = 2,
    display_name = 'Favorite Pizza'
  ),
  faketables::col_def(
    name = 'Rating',
    input = faketables::input_call(
      fun = shiny::sliderInput,
      args = list(label = NULL, min = 11, max = 20)
    ),
    cast = as.integer,
    width = 2
  )
)

Create the table definition with table_def()

t_def <- faketables::table_def(c_def)

Get data and create the faketable

pz <-
  jsonlite::read_json(
    path = 'https://www.jaredlander.com/data/FavoritePizzaPlaces.json',
    simplifyVector = TRUE
  ) |>
  tibble::as_tibble() |>
  tidyr::unnest(cols = c('Details', 'Coordinates')) |>
  dplyr::mutate(
    'Zip' = as.integer(.data$Zip),
    'FavoritePizza' = 'Cheese',
    'Rating' = 11L
  ) |>
  faketables::faketable(table_def = t_def, show_delete = list(width = 1))

Create the UI

ui <- bslib::page_navbar(
  title = 'Favorite Pizza Places',
  shinyjs::useShinyjs(),
  bslib::nav_panel(
    title = 'NYC',
    bslib::layout_columns(
      col_widths = c(4, 8),
      min_height = '500px',
      bslib::card(
        bslib::card_header('Add Favorite'),
        bslib::card_body(
          shiny::fluidRow(
            shiny::column(
              width = 12,
              shiny::fluidRow(
                shiny::column(
                  width = 6,
                  shiny::textInput('name', label = 'Name')
                ),
                shiny::column(
                  width = 6,
                  shiny::textInput('address', label = 'Address')
                )
              ),
              shiny::fluidRow(
                shiny::column(
                  width = 6,
                  shiny::selectInput(
                    'city',
                    label = 'City',
                    choices = c('Bronx', 'Brooklyn', 'New York', 'Queens', 'Staten Island'),
                    selected = 'New York')
                ),
                shiny::column(
                  width = 6,
                  shiny::numericInput(
                    'zip',
                    label = 'Zip',
                    value = 10001,
                    min = 10001,
                    max = 11697,
                    step = 1)
                  )
              ),
              shiny::fluidRow(
                shiny::column(
                  width = 6,
                  shiny::textInput('latitude', label = 'Latitude')
                ),
                shiny::column(
                  width = 6,
                  shiny::textInput('longitude', label = 'Longitude')
                )
              ),
              shiny::fluidRow(
                shiny::column(
                  width = 6,
                  shiny::textInput('favoritePizza', label = 'Favorite Pizza')
                ),
                shiny::column(
                  width = 6,
                  shiny::sliderInput(
                    'rating',
                    label = 'Pizza Rating',
                    min = 11,
                    max = 20,
                    value = 11)
                )
              )
            )
          ),
          shiny::fluidRow(
            shiny::actionButton('add', label = 'Add Data')
          )
        )
      ),
      bslib::card(
        full_screen = TRUE,
        bslib::card_header('Map'),
        bslib::card_body(
          leaflet::leafletOutput(outputId = 'map'),
        )
      )
    ),
    bslib::card(
      full_screen = TRUE,
      bslib::card_header('Table'),
      bslib::card_body(
        faketables::faketablesUI()
      )
    )
  )
)
#> Warning: Navigation containers expect a collection of
#> `bslib::nav_panel()`/`shiny::tabPanel()`s and/or
#> `bslib::nav_menu()`/`shiny::navbarMenu()`s. Consider using `header` or `footer`
#> if you wish to place content above (or below) every panel's contents.

Create the server

server <- function(input, output, session) {
  pz <- faketables::faketablesServer(faketable = pz)
  output$map <-
    leaflet::leaflet() |>
    leaflet::addTiles() |>
    leaflet::setView(-74.0060, 40.7128, 11) |>
    leaflet::renderLeaflet()

  shiny::observe({
    ins <- tibble::tibble(
      'Name' = input$name,
      'Address' = input$address,
      'City' = input$city,
      'State' = 'NY',
      'Zip' = as.integer(input$zip),
      'latitude' = as.numeric(input$latitude),
      'longitude' = as.numeric(input$longitude),
      'FavoritePizza' = input$favoritePizza,
      'Rating' = as.integer(input$rating)
    ) |>
      suppressWarnings()
    if (any(is.na(unlist(ins)) | unlist(ins) == '')) {
      shiny::showNotification(
        'Something went wrong. Please validate your input data and try again.',
        type = 'error'
      )
    } else {
      faketables::faketablesInsert(reactive_faketable = pz, data = ins)
    }
  }) |>
    shiny::bindEvent(input$add)

  shiny::observe({
    map_data <-
      pz()@data |>
      dplyr::mutate('.rowId' = dplyr::row_number()) |>
      dplyr::mutate(
        'label' = shiny::HTML(glue::glue('{.data$Name}<br>{.data$Address}, {.data$City}, NY, {.data$Zip}')),
        .by = '.rowId'
      ) |>
      dplyr::mutate(
        'fill_color' = dplyr::case_when(
          .data$label == 'cheese' ~ '#FFCA45',
          .default = '#FFCA45'
        )
      ) |>
      dplyr::select(-'.rowId')
    leaflet::leafletProxy('map', data = map_data) |>
      leaflet::clearMarkers() |>
      leaflet::addCircleMarkers(
        lng = ~longitude,
        lat = ~latitude,
        radius = ~Rating + 4,
        color = '#C9AA6E',
        weight = 4,
        opacity = 1,
        fillColor = ~fill_color,
        fillOpacity = 1,
        label = ~label
      )
  }) |>
    shiny::bindEvent(input$update, pz())
}

Run the app

shiny::shinyApp(ui, server)