Skip to content

Commit

Permalink
picker & selectize group shiny modules
Browse files Browse the repository at this point in the history
  • Loading branch information
pvictor committed Feb 20, 2018
1 parent 013ba9a commit bddb71d
Show file tree
Hide file tree
Showing 8 changed files with 739 additions and 0 deletions.
16 changes: 16 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export(knobInput)
export(materialSwitch)
export(multiInput)
export(panel)
export(pickerGroupServer)
export(pickerGroupUI)
export(pickerInput)
export(prettyCheckbox)
export(prettyCheckboxGroup)
Expand All @@ -30,6 +32,8 @@ export(progressBar)
export(progressSweetAlert)
export(radioGroupButtons)
export(searchInput)
export(selectizeGroupServer)
export(selectizeGroupUI)
export(sendSweetAlert)
export(shinyWidgetsGallery)
export(sliderTextInput)
Expand Down Expand Up @@ -68,15 +72,27 @@ importFrom(htmltools,tagList)
importFrom(htmltools,tags)
importFrom(htmltools,validateCssUnit)
importFrom(jsonlite,toJSON)
importFrom(shiny,NS)
importFrom(shiny,actionLink)
importFrom(shiny,addResourcePath)
importFrom(shiny,animationOptions)
importFrom(shiny,getDefaultReactiveDomain)
importFrom(shiny,icon)
importFrom(shiny,insertUI)
importFrom(shiny,observe)
importFrom(shiny,observeEvent)
importFrom(shiny,reactive)
importFrom(shiny,reactiveValues)
importFrom(shiny,reactiveValuesToList)
importFrom(shiny,restoreInput)
importFrom(shiny,runApp)
importFrom(shiny,selectizeInput)
importFrom(shiny,shinyAppFile)
importFrom(shiny,singleton)
importFrom(shiny,sliderInput)
importFrom(shiny,updateSelectizeInput)
importFrom(stats,aggregate)
importFrom(stats,as.formula)
importFrom(utils,capture.output)
importFrom(utils,modifyList)
importFrom(utils,packageVersion)
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ shinyWidgets 0.4.1.960
* New function `updateSearchInput` to update `searchInput` server-side [#52](https://github.com/dreamRs/shinyWidgets/issues/52).
* New argument `inline` to `prettySwitch`, `prettyToggle` and `prettyCheckbox` to position checkboxes side by side.
* New argument `html` to `confirmSweetAlert` and `sendSweetAlert` to pass HTML tags in alert window [#48](https://github.com/dreamRs/shinyWidgets/issues/48).
* New Shiny modules to create dependent slect menu : `selectizeGroup` and `pickerGroup`.



Expand Down
236 changes: 236 additions & 0 deletions R/module-pickerGroup.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@

#' @title Picker Group
#'
#' @description Group of mutually dependent `pickerInput` for filtering data.frame's columns.
#'
#' @param id Module's id.
#' @param params a named list of parameters passed to each `pickerInput`, you can use :
#' `inputId` (obligatory, must be variable name), `label`, `placeholder`.
#' @param label character, global label on top of all labels.
#' @param btn_label reset button label.
#' @param options See \code{\link{pickerInput}} options argument.
#'
#' @return a \code{reactive} function containing data filtered.
#' @export
#'
#' @name pickerGroup-module
#'
#' @importFrom htmltools tagList tags singleton
#' @importFrom shiny NS actionLink icon
#' @importFrom utils modifyList
#'
#' @examples
#' \dontrun{
#'
#' if (interactive()) {
#'
#' library(shiny)
#' library(shinyWidgets)
#'
#'
#' data("mpg", package = "ggplot2")
#'
#'
#' ui <- fluidPage(
#' fluidRow(
#' column(
#' width = 10, offset = 1,
#' tags$h3("Filter data with picker group"),
#' panel(
#' pickerGroupUI(
#' id = "my-filters",
#' params = list(
#' manufacturer = list(inputId = "manufacturer", title = "Manufacturer:"),
#' model = list(inputId = "model", title = "Model:"),
#' trans = list(inputId = "trans", title = "Trans:"),
#' class = list(inputId = "class", title = "Class:")
#' )
#' ), status = "primary"
#' ),
#' dataTableOutput(outputId = "table")
#' )
#' )
#' )
#'
#' server <- function(input, output, session) {
#' res_mod <- callModule(
#' module = pickerGroupServer,
#' id = "my-filters",
#' data = mpg,
#' vars = c("manufacturer", "model", "trans", "class")
#' )
#' output$table <- renderDataTable(res_mod())
#' }
#'
#' shinyApp(ui, server)
#'
#' }
#'
#' }
pickerGroupUI <- function(id, params, label = NULL, btn_label = "Reset filters", options = list()) {

# Namespace
ns <- NS(id)

# # ids
# ids <- unlist(lapply(params, `[[`, "inputId"), use.names = FALSE)
# cond <- paste0(paste0("[", paste(paste0("input['", ns(ids), "']"), collapse = ", "), "]"), ".length > 0")

tagList(
singleton(
tagList(
tags$link(
rel="stylesheet",
type="text/css",
href="shinyWidgets/modules/styles-modules.css"
), toggleDisplayUi()
)
),
tags$b(label),
tags$div(
class="btn-group-justified picker-group",
role="group", `data-toggle`="buttons",
lapply(
X = seq_along(params),
FUN = function(x) {
input <- params[[x]]
tagSelect <- tags$div(
class="btn-group",
pickerInput(
inputId = ns(input$inputId),
label = input$label,
selected = input$selected,
choices = input$choices,
multiple = TRUE,
width = "100%",
options = modifyList(
x = options,
val = list(
`actions-box` = FALSE,
`selected-text-format`= "count > 5",
`count-selected-text` = "{0} choices (on a total of {1})"
)
)
)
)
return(tagSelect)
}
)
),
actionLink(
inputId = ns("reset_all"),
label = btn_label,
icon = icon("remove"),
style = "float: right;"
)
)

}

#' @param input standard \code{shiny} input.
#' @param output standard \code{shiny} output.
#' @param session standard \code{shiny} session.
#' @param data a \code{data.frame}, or an object coercible to \code{data.frame}.
#' @param vars character, columns to use to create filters,
#' must correspond to variables listed in \code{params}.
#'
#' @export
#'
#' @rdname pickerGroup-module
#' @importFrom shiny observeEvent reactiveValues reactive observe reactiveValuesToList
#' @importFrom stats aggregate as.formula
pickerGroupServer <- function(input, output, session, data, vars) {

data <- as.data.frame(data)

# Namespace
ns <- session$ns

# toggleDisplayServer(session = session, id = ns("reset_all"), display = "none")

lapply(
X = vars,
FUN = function(x) {
vals <- sort(unique(data[[x]]))
updatePickerInput(
session = session,
inputId = x,
choices = vals
)
}
)

observeEvent(input$reset_all, {
lapply(
X = vars,
FUN = function(x) {
vals <- sort(unique(data[[x]]))
updatePickerInput(
session = session,
inputId = x,
choices = vals
)
}
)
})

data_r <- reactiveValues()

observe({
inputs <- reactiveValuesToList(input)
inputs[["reset_all"]] <- NULL
indicator <- lapply(
X = vars,
FUN = function(x) {
data[[x]] %inT% inputs[[x]]
}
)
data$indicator <- Reduce(f = `&`, x = indicator)
if (all(data$indicator)) {
toggleDisplayServer(session = session, id = ns("reset_all"), display = "none")
} else {
toggleDisplayServer(session = session, id = ns("reset_all"), display = "block")
}
lapply(
X = vars,
FUN = function(x) {
# tmp <- unique(data[, c(x, "indicator")])
tmp <- aggregate(
formula = as.formula(paste("indicator", x, sep = "~")),
data = data,
FUN = Reduce, f = `|`
)
updatePickerInput(
session = session,
inputId = x,
choices = tmp[[x]],
selected = inputs[[x]],
choicesOpt = list(
disabled = !tmp$indicator,
style = ifelse(
!tmp$indicator,
yes = "color: rgba(119, 119, 119, 0.5);",
no = ""
)
)
)
}
)
})


return(reactive({
indicator <- lapply(
X = vars,
FUN = function(x) {
data[[x]] %inT% inputs[[x]]
}
)
indicator <- Reduce(f = `&`, x = indicator)
data <- data[indicator, ]
return(data)
}))
}



Loading

0 comments on commit bddb71d

Please sign in to comment.