Writing If condition inside DT datatable options? - shiny

Apologies for not being able to provide a reproducible example, but below is the options for my datatable. Basically, if the screenshot button is pressed - I don't want the scroll feature enabled - otherwise it should be enabled. Thank you for any help or recommendations! The if statement initially evaluates as false, but the scroll feature is still disabled by default.
Also, does anyone know the meaning of life?
` options = list(dom = 't', paging = FALSE, ordering = FALSE,
#pageLength = -1,
if(input$screenshot > 0){
scrollY=NULL
} else {
scrollY='50vh'
}
, scrollCollapse = TRUE`

Keep it simple. Write your if condition outside the DT renderer, inside an observer to a reactive variable. Also, instead of using an action button for screenshot I would suggest you to use a toggle button. This would allow you to enable and disable scrolling instead of just disabling it altogether.
# You initialize the table with scrolling enabled
react <- reactiveValues(scrollCondition="50vh")
# Toggle button returns TRUE when enabled and FALSE when disabled. So when screenshots are set to TRUE, we make the scrollY property NULL.
observeEvent(input$screenshot,{
if(input$screenshot==TRUE){
react$scrollCondition <- NULL
}else{
react$scrollCondition <- "50vh'"
}
})
`options = list(dom = 't', paging = FALSE, ordering = FALSE,
scrollY= react$scrollCondition,
scrollCollapse = TRUE`
Hope this helps.

Related

data table uiOutput disappears on redraw

I am displaying widgets within a DT datatables in an R Shiny app.
Following a similar approach to here, widgets are inserted as text into the data table. Then using the option escape = FALSE, the text of the widgets is interpretated as HTML and the widget is displayed.
This approach has worked very well, until I came to redraw the datatable. On redraw the widgets within the table no longer appear. You can test with the following example. When "Redraw" is clicked, the UI output showing the text "here" disappears.
# UI
ui = fluidPage(
actionButton("draw", "Redraw"),
# uiOutput("ui"),
DT::dataTableOutput("classify_table")
)
# server
server = function(input, output, session) {
output$ui = renderUI({ p("here") })
output$classify_table <- DT::renderDataTable({
df = data.frame(
rows = input$draw,
UI = as.character(uiOutput("ui")),
stringsAsFactors = FALSE
)
DT::datatable(
df,
escape = FALSE,
options = list(
dom = "t",
preDrawCallback = DT::JS('function() { Shiny.unbindAll(this.api().table().node()); }'),
drawCallback = DT::JS('function() { Shiny.bindAll(this.api().table().node()); } ')
)
)
})
}
# run
shinyApp(ui, server)
My best hypothesis is that Shiny ends up with two uiOutput("ui") bound. This would mean it does not display at the uiOutput("ui") in the redrawn table.
Supporting this hypothesis: if we uncomment uiOutput("ui") from line four, then the text "here" never appears in the data table, just like after redrawing.
Contrary evidence: the whole point of the callbacks is to unregister the previous uiOutput("ui") and to reregister the new uiOutput("ui") which should prevent this cause.
Any idea what is causing this behavior and how to fix it? Even suggestions for how to better debug this behavior would be helpful.
Another possible solution is to bind the UI component to shiny directly, instead of in the callback. But I don't know how to determine the JavaScript for this.
Based on the comment from #Stéphane Laurent, I found this answer by them (search term user:1100107 [dt] unbind).
I inserted this code into the UI
tags$script(HTML(
"Shiny.addCustomMessageHandler('unbindDT', function(id) {
var $table = $('#'+id).find('table');
if($table.length > 0){
Shiny.unbindAll($table.DataTable().table().node());
}
})"
))
and this code at the start of the DT::renderDataTable({:
session$sendCustomMessage("unbindDT", "classify_table")
Note that if working in a module, we need to wrap with ns as so:
session$sendCustomMessage("unbindDT", ns("classify_table"))

New Buttons in Interactive Grid toolbar

I need to add a new button to existing IG toolbar, which will set a specific value in the table column and then save the record.
Is there any way to create new buttons/change the behavior of existing Interactive Grid toolbar buttons?
I see you are using APEX 5.1. Yes, you can customise toolbar buttons in an interactive grid. For example, you can modify the look and feel of the Save and Add Row buttons and also add a Delete button. Select your interactive grid region and in the property editor, enter a value for Advanced > Static ID. Select Attributes > Advanced > JavaScript Initialization Code and input the following:
function(config) {
let $ = apex.jQuery,
toolbarData = $.apex.interactiveGrid.copyDefaultToolbar(),
toolbarGroup = toolbarData.toolbarFind("actions3");
addrowAction = toolbarData.toolbarFind("selection-add-row"),
saveAction = toolbarData.toolbarFind("save"); // Save button
// adding a "Delete" button
toolbarGroup.controls.push({type: "BUTTON",
action: "selection-delete",
icon: "icon-ig-delete",
iconBeforeLabel: true,
hot: true
});
// Modifying the buttons
addrowAction.icon = "icon-ig-add-row";
addrowAction.iconBeforeLabel = true;
addrowAction.hot = true;
saveAction.iconBeforeLabel = true;
saveAction.icon ="icon-ig-save-as";
saveAction.hot = true;
//storing the config
config.toolbarData = toolbarData;
return config;
}
Now run the page to see the customisation.
Here's a nice video that shows how to customise IG toolbar.
https://www.youtube.com/watch?v=_PBdBAfPBfQ

Shiny selectInput(multiple = TRUE) problem with mobile devices

I developed a dashboard to monitor covid-19 cases in Brazil using shiny and flexdashboard. It's working fine, but not on mobile devices (at least in some of them). At the sidebar there is a selectinput() with multiple=TRUE, and the problem is that every time the mobile user tries to select a value to update the plots, the screen keyboard is shown and the whole app is realoaded before the selection (for the correct usage the user needs to select the states and click on "Atualizar" button to update).
I tried to solve it by duplicating the siderbar section, and use {.no-mobile} for the first one, and {.mobile) for the second, and using multiple=FALSE in this second selectinput(). Unfortunately it won't work, and both sections were shown overlapping.
I thought about another way (and i don't know how to do it), using something like multiple=ifelse("is mobile test",FALSE,TRUE).
My questions are: Is there a way to test if the browser is mobile? Is there another approach do solve this problem?
Any help will be highly appreciated.
App link (code embed): https://costafilho.shinyapps.io/monitor_covid19/
Github project: https://github.com/sergiocostafh/monitor_covid19
Problematic line:
selectInput("estado",h3("Estados"),choices = est_nome, selected = "Sao Paulo", multiple = TRUE)
Could you try this app on your mobile:
library(shiny)
js <- '
function(){
$(".selectize-input input").attr("readonly", "readonly");
}
'
shinyApp(
ui = fluidPage(
selectizeInput("variable", "Variable:",
c("Cylinders" = "cyl",
"Transmission" = "am",
"Gears" = "gear"),
multiple = TRUE,
options = list(onInitialize = I(js))
),
tableOutput("data")
),
server = function(input, output) {
output$data <- renderTable({
mtcars[, c("mpg", input$variable), drop = FALSE]
}, rownames = TRUE)
}
)
The keyboard should not appear.

Kendo multiselect enable summary tag mode after a few selections are made

I have a kendo multiselect i have set up in summary tag mode with this template:
# if (dataItems.length < 4) { #
# for (var idx = 0; idx < values.length; idx++) {#
#:dataItems[idx].Name#
# if (idx < values.length - 1) {#</li><li class="k-button" unselectable="on"> # } #
#}#
# } else {#
#:values.length# item(s) selected
# } #
This works but it's hacky. What it does is show the first few entries and then group them if you choose four or more. The kendo ui version of this control has a property that allows what i want to do here to work automatically. [kendoMultiSelectSummaryTag]="3"
However that property doesn't seem to be available unless i'm looking in the wrong spot. Can someone tell me how to use it? I would like the default functionality to work because that allows deletions from the selection display.
As far as I can tell there isn't a simple property you can set that will do this for you. Fortunately the solution isn't too tricky. The idea will be to set the default tagMode to 'multiple' (which is it by default), then to create an event handler which will change the tagMode to 'single' when the number of items is crosses your threshold.
Your multiselect definition will need to attach the event handler to the change event:
#(Html.Kendo().MultiSelect()
.Name("multiSelect")
// other properties as needed of course
.Events(events => events
.Change("tagModeSet")
)
)
The javascript event handler will then look something like this:
function tagModeSet() {
// Get the currently selected values and tagMode
var selectedValues = this.value();
var currentTagMode = this.options.tagMode;
var newTagMode = currentTagMode;
// Test to see if you have crossed the threshold
if (selectedValues.length <= 3) {
newTagMode = "multiple";
} else {
newTagMode = "single"
}
// Update the tagMode if needed
if (newTagMode != currentTagMode) {
this.value([]);
this.setOptions({
tagMode: newTagMode
});
this.value(selectedValues);
}
}
Note that when you update the tagMode you first clear the items, then adjust the mode, then re-select the items. Hope that helps.
Reference

How can I clear the focus from a desensitized GtkWidget - GtkSpinButton with property sensitive = false

Background: I have a few tabs set up in my GtkNotebook, and when certain conditions are met on the main tab, then input fields in the 'test signals' tab are accordingly disabled.
When the input inside a GtkSpinButton is highlighted on the 'test signals' tab and the GtkSpinButton's property sensitive is set to false, the text within the GtkSpinButton remains highlighted. Because sometimes there are no other editable fields on this tab, the text remains highlighted until another widget has its property sensitive set to true.
This just looks sloppy to me, so I would like to stop this behavior and have the widgets that are set to sensitive = false all cleared of focus or highlighting. Any idea how to un-highlight the text within the GtkSpinButton, maybe before setting sensitive = false?
To get rid of a selection you can use the gtk_editable_select_region() function. This is a method on GtkEditable, an interface that both GtkEntry and GtkSpinButton satisfy. You can convert either of these to GtkEditable with GTK_EDITABLE(). For example:
gtk_editable_select_region(GTK_EDITABLE(spinbutton), 0, 0);