Rshiny Module Observer Issue

I’m having trouble with observers & modules in a huge app. I created a smaller example.

What I want to do:

  1. User makes selections
  2. Database call is done based on these selections –> MAIN_DATA (not on the fly)
  3. Data is sub-filtered initally by a single radio-buttons –> MAIN_DATA_FILTERED (on the fly)
  4. Data is sub-filtered and shown based on the selected tab (each tab has a different type of visualization). –> MAIN_DATA_FILTERED_FILTERED (on the fly)

In one of the visualizations (one of the tabs) I’m using leaflet as a location selector. Initially it goes well: Select an area –> filter the data by this area & show it in a modal.

If I change ANYTHING in my last selections-menu (step 4), however I get reactivity issues. 1 change = 1 modal each click. n changes = n modals popping up, which crashed the system. The problem is caused by a reactivity issue in the last selections module. I located the problem to this module by adding a modal to it. This is what is shown in the example.

Whenever I change this module else goes wrong.

Below is the snippet I created: Whenever I change my TAB it shows the modal. Changing it to an observe doesnt help either. How do I get the extra selections to change when the input$tab changes, but make sure no extra observers are created?

Now: Every change in the tab creates an extra observer, every change in the selections creates an extra observer for the leaflet map etc.

# Load necessary libraries
library(shiny)
library(dplyr)

# Define the UI for the selections module
# This function creates a select input with multiple selection enabled
selectionsUI <- function(id) {
  ns <- NS(id)
  selectInput(ns("variableSelect"), "Choose some:", choices = c("X", "Z"), multiple = TRUE)
}

# Define the server logic for the selections module
# This function returns the selected variables from the select input
selectionsServer <- function(id) {
  moduleServer(id, function(input, output, session) {
    reactive({
      input$variableSelect
    })
  })
}

# Define the UI for the last selections module
# This function creates a button and an output UI element
lastSelectionsUI <- function(id) {
  ns <- NS(id)
  tagList(
    actionButton(ns("infoButton"), "INFORMATION BUG"),
    uiOutput(ns("lastSelector"))
  )
}

# Define the server logic for the last selections module
# This function shows a modal when the button is clicked and updates the last filter based on the selected tab
lastSelectionsServer <- function(id, selectionsSnapshot, selectedTab) {
  moduleServer(id, function(input, output, session) {
    lastFilter <- reactiveVal(NULL)
    observeEvent(input$infoButton, {
      showModal(
        modalDialog(
          title = "This is not working??",
          paste0("Selected tab: ", selectedTab)
        )
      )
    })

    output$lastSelector <- renderUI({
      ns <- session$ns
      if (selectedTab == "Y below zero") {
        tagList(
          selectInput(label = "LAST FILTER", ns("filterAgain"), choices = selectionsSnapshot(), multiple = TRUE)
        )
      } else {
        tagList()
      }
    })

    observe({
      lastFilter(input$filterAgain)
      print(lastFilter())
    })

    return(lastFilter)
  })
}

# Define the UI for the test module
# This function creates a layout with two columns and a tabset panel
testUI <- function(id) {
  ns <- NS(id)
  tagList(
    column(2, uiOutput(ns("lastSelections"))),
    column(6, tabsetPanel(
      id = ns("tab"),
      tabPanel("Y above zero", uiOutput("Y_above_zero")),
      tabPanel("Y below zero", uiOutput(ns("Y_below_zero"))),
    ))
  )
}

# Define the server logic for the test module
# This function creates a reactive expression that filters data based on the selected tab and the last filter
testServer <- function(id, data, selectionsSnapshot) {
  moduleServer(id, function(input, output, session) {
    output$lastSelections <- renderUI({
      ns <- session$ns
      lastSelectionsUI(ns("last"))
    })

    lastFilter <- reactiveVal(NULL)
    observeEvent(input$tab, {
      print("working")
      myFilter <- lastSelectionsServer("last", selectionsSnapshot, input$tab)
      lastFilter(myFilter)
    })

    observe({
      print("*****")
      print(lastFilter())
      print("******")
    })

    # Create a reactive expression that filters data based on the selected tab and the last filter
    filteredData <- reactive({
      df <- data()
      if (input$tab == "Y above zero") {
        df <- df[df$Y > 0, ]
      } else if (input$tab == "Y below zero") {
        df <- df[df$Y <= 0, ]
      }

      # Filter based on the last filter
      if (!is.null(lastFilter())) {
        filterValue <- lastFilter()()
        df <- df %>% select(all_of(filterValue))
      }
      df
    })

    # Add an action button to the UI for each tab
    output$Y_above_zero <- renderUI({
      if (input$tab == "Y above zero") {
        actionButton(ns("showDataAbove"), "Show Data")
      }
    })

    output$Y_below_zero <- renderUI({
      if (input$tab == "Y below zero") {
        ns <- session$ns
        actionButton(ns("showDataBelow"), "Show Data")
      }
    })

    # Show the filtered data in a modal when the button is clicked
    observeEvent(input$showDataAbove, {
      showModal(modalDialog(
        title = "Data where Y is above zero",
        renderTable(filteredData())
      ))
    })

    observeEvent(input$showDataBelow, {
      showModal(modalDialog(
        title = "Data where Y is below zero",
        renderTable(filteredData())
      ))
    })
  })
}

# Define the main page UI
# This function creates a layout with a main filter, an intermediate filter, and a test module
mainPageUI <- function(id) {
  ns <- NS(id)
  fluidPage(
    h1("Main filter"),
    selectionsUI(ns("selections")),
    actionButton(ns("getData"), "Get data from database"),
    tags$hr(),
    tags$br(),
    h1("Intermediate on-the-fly filter"),
    radioButtons(ns("testFilter"), "Filter data", choices = c("X Above zero", "X Below zero")),
    tags$hr(),
    tags$br(),
    wellPanel(fluidRow(testUI(ns("test"))))
  )
}

# Define the main page server
# This function gets data from a database and starts the test server when the test filter is changed
mainPageServer <- function(id) {
  moduleServer(id, function(input, output, session) {
    selections <- selectionsServer("selections")

    observeEvent(input$getData, {
      req(selections)
      print("Getting data from database")
      # Save a snapshot of the selections
      selectionsSnapshot <- reactiveVal(selections())

      # Get some data from a database
      data <- reactive({
        data.frame(X = rnorm(10), Y = rnorm(10), Z = rnorm(10))
      })
      print("Got data from database")
      observeEvent(input$testFilter, {
        # Filter the initial data on the fly
        filteredData <- reactive({
          if (input$testFilter == "X Above zero") {
            data()[data()$X > 0, ]
          } else {
            data()[data()$X <= 0, ]
          }
        })

        # Start the test server inside of this observeEvent
        testServer("test", filteredData, selectionsSnapshot)
      })
    })
  })
}

# Define the shiny server
server <- shinyServer(function(global, input, output, session) {
  observe({
    mainPageServer(("main_page"))
  })
})

# Define the shiny UI
ui <- fluidPage(mainPageUI("main_page"))

# Run the application
shinyApp(ui = ui, server = server)

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật