generate main panel with action button [R-Shiny]

#1
Hi,

I'm not an expert in programing, but I try to build an application with Shiny. You could find the entire code below for a better understanding of where I'm blocked.

I start by generating buttons in the side panel. When I click on one of them, I generate buttons in the main panel. When I click on one of them (... :) ), I would like to see many things, but there it doesn't work. I can not catch the last action to genrate my main panel.

What are the rules to have "observer" functions in "observer" or "reactive" functions?
When I load the page and click on one of the buttons in the side panel, I have to re-load to catch the second click...


could you help me please?

many thanks.


Code:
UI.R

library(shiny)
source('ref.R')

PAGE_WIDTH <- 1700
span.widths <- Reduce(paste, sapply(1:12, function(n) paste0('.span', n, '{width:', floor(n * PAGE_WIDTH / 12), 'px;}')))

shinyUI(fluidPage(
  #Barre de navigation
  navbarPage( title="Test", windowTitle="Test", collapsible=TRUE,
          tabPanel("page 1",
  
  #Sidebar Panel
          sidebarLayout(position="left", fluid=TRUE, 
                        
              sidebarPanel( width= 2, 
                            h4("c1/c2"),
                              do.call(verticalLayout,row.list.c1)
                              
                           ),
              mainPanel(width = 10,
                        h4(textOutput('txtCurrentc1')),
                        uiOutput('c2.buttons'),
                        h4(textOutput('txtc2Name'))
                        
                       
                        
                        ))
  ),
          tabPanel("page 2")
  )))



server.R


source('ref.R')





### MAIN SERVER LOOP

shinyServer(function(input, output, session) {

  ###############################################  
  button.states.c1 <- reactive({
    sapply(as.character(unique(df.parts$c1)), function(c1) {input[[paste0("btn",c1)]]})
  })  
  
  # c1 # selection button observer
  observe({
    # Detect which button was pressed
    states.c1 <<- button.states.c1()
    change.c1 <<- states.c1 != last.states.c1
    if (sum(change.c1) > 0) {
      print("checkpoint")
      
      currentc1 <<- names(which(change.c1))[1]
      
      last.states.c2 <<- sapply(as.character(df.parts$c2[df.parts$c1 == as.character(currentc1)]), function(x) 0)
      states.c2 <<- sapply(as.vector(df.parts[df.parts$c1 == currentc1,2]), function(x) 0)
      print("Current c1 Script Executed")
      #Update the UI
      output$txtCurrentc1 <- renderText(paste("Colonne selectionnée ",currentc1))
      output$c2.buttons <- renderc2Buttons(currentc1)
      
    }
    
    # Remember button states
    last.states.c1 <<- states.c1
    
  })  

  
######################################################
  
button.states.c2 <- reactive({
  
  sapply(as.vector(df.parts[df.parts$c1 == currentc1,2]), function(cl) input[[paste0('btn', cl)]])
  
})

######################################################


  # c2 # selection button observer
  observe({
    # Detect which button was pressed
    
    states.c2 <<- button.states.c2()
    print(states.c2)
    change.c2 <- states.c2 != last.states.c2
    print(change.c2)
    if (sum(change.c2) != 0) {
      print("checkpoint c2")
      currentc2 <<- names(which(change.c2))[1]
      # Update the UI
      output$txtc2Name <- renderText(as.character(df.parts$c2[df.parts$c2 == as.character(currentc2)]))      
    }
    
    # Remember button states
    last.states.c2 <<- states.c2
  })
})




ref.R


currentc1 <- NULL

#Creation du data frame
df.parts <- data.frame(c1 = c("a","a","a","a","a","b","b","b","c","c","c","c","c","c"), c2 = c("1","2","3","4","5","6","7","8","9","10","11","12","13","14"))

rownames(df.parts) <- df.parts$c2


row.list.c1 <- lapply(unique(df.parts$c1), function(p){
  c1.buttons <- lapply(p, function(c1){
    actionButton(inputId=paste0("btn",c1), label=c1)
  })
  fluidRow(id= p, c1.buttons)
})



last.states.c1 <<- sapply(as.character(unique(df.parts$c1)), function(Y) 0)

#generation de la liste de bouttons c2 en fonction de c1 selectionne
renderc2Buttons <- function(currentc1) {
  renderUI({
    lapply(rownames(df.parts[df.parts$c1 == as.character(currentc1), ]), function(cl) {
      with(df.parts[df.parts$c2 == cl, ], 
           actionButton(inputId=paste0('btn', cl),label=cl))
      
    })
    
    
  })
}
 
#2
Catch it!

The problem was to have "observer" in other "observer":

here is the complete code which works:

UI.R

Code:
library(shiny)
source('ref.R')

PAGE_WIDTH <- 1700
span.widths <- Reduce(paste, sapply(1:12, function(n) paste0('.span', n, '{width:', floor(n * PAGE_WIDTH / 12), 'px;}')))

shinyUI(fluidPage(
  #Barre de navigation
  navbarPage( title="Test", windowTitle="Test", collapsible=TRUE,
              tabPanel("page 1",
                       
                       #Sidebar Panel
                       sidebarLayout(position="left", fluid=TRUE, 
                                     
                                     sidebarPanel( width= 2, 
                                                   h4("c1/c2"),
                                                   do.call(verticalLayout,row.list.c1)
                                                   
                                     ),
                                     mainPanel(width = 10,
                                               h4(textOutput('txtCurrentc1')),
                                               uiOutput('c2.buttons'),
                                               h4(textOutput('txtc2Name'))
                                               
                                               
                                               
                                     ))
              ),
              tabPanel("page 2")
  )))
server.R:

Code:
source('ref.R')


### MAIN SERVER LOOP

shinyServer(function(input, output, session) {

  ###############################################  
  button.states.c1 <- reactive({
    sapply(as.character(unique(df.parts$c1)), function(c1) {input[[paste0("btn",c1)]]})
  })  
  
  # c1 # selection button observer
  observe({
    # Detect which button was pressed
    states.c1 <<- button.states.c1()
    change.c1 <<- states.c1 != last.states.c1
    if (sum(change.c1) > 0) {

      currentc1 <<- names(which(change.c1))[1]
      
      last.states.c2 <<- sapply(as.character(df.parts$c2[df.parts$c1 == as.character(currentc1)]), function(x) 0)

      states.c2 <<- sapply(as.character(df.parts$c2[df.parts$c1 == as.character(currentc1)]), function(x) 0)

      #Update the UI
      output$txtCurrentc1 <- renderText(paste("Colonne selectionnée ",currentc1))
      output$c2.buttons <- renderc2Buttons(currentc1)
      
          
            # c2 # selection button observer
            observe({
              # Detect which button was pressed
              
              #states.c2 <<- button.states.c2()
              states.c2 <<- sapply(as.character(df.parts$c2[df.parts$c1 == as.character(currentc1)]), function(cl) {input[[paste0("btn",cl)]]})
              if ((!is.list(states.c2)) & (!is.list(last.states.c2))==TRUE){
              change.c2 <<- states.c2 != last.states.c2

                if (sum(change.c2) != 0) {
                  
                  currentc2 <<- names(which(change.c2))[1]
                  # Update the UI
                  output$txtc2Name <- renderText(as.character(df.parts$c2[df.parts$c2 == as.character(currentc2)]))      
                }
              
              # Remember button states
              last.states.c2 <<- states.c2
            }
            })
      
    }
    
    # Remember button states
    last.states.c1 <<- states.c1
    
  })  
  
})
ref.R:

Code:
currentc1 <- NULL

#Creation du data frame
df.parts <- data.frame(c1 = c("a","a","a","a","a","b","b","b","c","c","c","c","c","c"), c2 = c("1","2","3","4","5","6","7","8","9","10","11","12","13","14"))

rownames(df.parts) <- df.parts$c2


row.list.c1 <- lapply(unique(df.parts$c1), function(p){
  c1.buttons <- lapply(p, function(c1){
    actionButton(inputId=paste0("btn",c1), label=c1)
  })
  fluidRow(id= p, c1.buttons)
})



last.states.c1 <<- sapply(as.character(unique(df.parts$c1)), function(Y) 0)

#generation de la liste de bouttons c2 en fonction de c1 selectionne
renderc2Buttons <- function(currentc1) {
  renderUI({
    lapply(rownames(df.parts[df.parts$c1 == as.character(currentc1), ]), function(cl) {
      with(df.parts[df.parts$c2 == cl, ], 
           actionButton(inputId=paste0('btn', cl),label=cl))
      
    })
    
    
  })
}