Shiny conditionalPanel always appears - shiny

I built a small application making use of a conditional Panel which worked out of the box.
A second attempt has been less satisfying. The issue is that the conditional panels both show up no matter whether the conditions are met or not.
Here's what I have in a stripped down version:
library(shiny)
source('distplot.r')
ui<-fluidPage(
fluidRow(
radioButtons("intype", 'Data or Statistics?',
c(Data="d", Statistics="s")),
#Only show this if sample data are to be entered
conditionalPanel(
condition = "input$intype == 'd'",
textInput('x', 'Sample Data (Comma Separated)', value='')),
#Only shows this panel for summary statitics (sd or sigma if known)
conditionalPanel(
condition = "input$intype == 'r'",
numericInput('m','Sample Mean',value=''),
numericInput('sd','SD (Population or Sample)',value=''),
numericInput('n','Sample size',value=''))
)
)
server<-function(input, output){
DTYPE<-eventReactive(input$go,{input$dtype})
output$plot<-renderPlot({hist(runif(1000))})
}
shinyApp(ui=ui, server=server)
The two conditional panels always appear no matter the value of input$intype.

You need to use input.intype and not input$intype in your condition. Moreover intype can only be 'd' or 's' in your example, and you use 'r' in your condition.
Details section from ?shiny::conditionalPanel :
In the JS expression, you can refer to input and output JavaScript objects that contain the current values of input and output. For example, if you have an input with an id of foo, then you can use input.foo to read its value. (Be sure not to modify the input/output objects, as this may cause unpredictable behavior.)

Related

Combine two nested IF statements with multiple criteria

I have two columns of data in "Meds" sheet...
MedContinuing AgeAtMedStop
Yes "Blank"
Yes 72.22
No "Blank"
No 72.57
"Blank" 73.85
I am writing a formula in a separate sheet to return 1 or 0 based on the following:
If MedContinuing is "Blank", do nothing
If MedContinuing is "No" and AgeAtMedStop is blank, do nothing
If MedContinuing is "Yes" and AgeAtMedStop is "Blank", return 1. If AgeAtMedStop is a number, return 0.
If MedContinuing is "No" and AgeAtMedStop is a number, return 1. Otherwise, return nothing.
I was able to write two separate functions (see below) for when MedContinuing is "Yes" or when it is "No", but I need to combine both into one formula.
When it's Yes...
=IF(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="","",
IF(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="No","",
IF(AND(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="Yes",INDEX(Meds!2:2,MATCH("AgeAtMedStop",Meds!$1:$1,0))=""),1,0)))
When it's No...
=IF(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="","",
IF(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="Yes","",
IF(AND(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="No",INDEX(Meds!2:2,MATCH("AgeAtMedStop",Meds!$1:$1,0))=""),"",
IF(AND(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="No",INDEX(Meds!2:2,MATCH("AgeAtMedStop",Meds!$1:$1,0))>0),1,0))))
EDIT: Solution
Using Peter K's logic...
=IF(INDEX(Meds!6:6,MATCH("MedContinuing",Meds!$1:$1,0))="","",
IF(AND(INDEX(Meds!6:6,MATCH("MedContinuing",Meds!$1:$1,0))="No",INDEX(Meds!6:6,MATCH("AgeAtMedStop",Meds!$1:$1,0))=""),"",
IF(AND(INDEX(Meds!6:6,MATCH("MedContinuing",Meds!$1:$1,0))="Yes",INDEX(Meds!6:6,MATCH("AgeAtMedStop",Meds!$1:$1,0))=""),1,
IF(AND(INDEX(Meds!6:6,MATCH("MedContinuing",Meds!$1:$1,0))="Yes",INDEX(Meds!6:6,MATCH("AgeAtMedStop",Meds!$1:$1,0))>0),0,
IF(AND(INDEX(Meds!6:6,MATCH("MedContinuing",Meds!$1:$1,0))="No",INDEX(Meds!6:6,MATCH("AgeAtMedStop",Meds!$1:$1,0))>0),1,"")))))
It is not entirely clear from your question why you would use INDEX and MATCH functions for such straightforward problem ?
I suggest to start with the basic nested if function :
=IF(A2="";"";IF(A2="No";IF(B2="";"";1);IF(B2="";1;0)))
You can put this function next to your two columns, and then copy to another worksheet, so the references are taken care of by Excel.
I also assume that your data is clean and correct i.e. only the 3 possible values for MedContinuing ("Yes", "No" or blank) and 2 for AgeAtMedStop (blank or a number) exist in your columns, so no IF test is needed to eliminate other possible values.
You can try this method below
I have created a helper table for the logic you require, it will help to update or extend the logic in future
Formula in cell C2 is
=INDEX($F$2:$G$4,MATCH(A2,$E$2:$E$4,0),IF(B2="Blank",1,IF(ISNUMBER(B2),2,0)))

Powerbuilder modify row columns

I have more rows. And i want for the rows with status AA1 a column protected and for the rows with status different than AA1 the same column unprotected.
So I wrote this:
ll_count = dw_list.RowCount()
if ll_count > 0 then
for i = 1 to ll_count
if dw_list.object.status[i] = 'AA1' then
dw_list.modify("f_change[i].Protect='1")
//dw_list.Object.f_change[i].modify("f_change[i].Protect='1")
dw_list.Object.f_change[i].Background.Color = gf_get_btnface()
end if
if dw_list.object.status[i] <> 'AA1' then
dw_list.modify("f_change[i].Protect='0'")
end if
next
end if
But dw_list.modify("f_change[i].Protect='1'") is not correct. Neither dw_list.Object.f_change[i].modify("f_change[i].Protect='1").
If I just write dw_list.modify("f_change.Protect='1'") it modifies all the rows.
I woud do this without programming a single line, but by editing the datawindow design.
Open the datawindow in design mode
Select the desired column
In the 'General' tab, click on the small icon nearby 'Protect'.
Insert there the condiction to protect or not that column: if( status = 'AA1', '0', '1')
Done for all your data.
The same process can be applied to many characteristics of data window columns (color, background color, visible, pointer, position,...)
Alternatively, you could put the condition programmatically, but I would only do it if you need to change the protection scheme 'on the fly'. Anyway, the principle is to set the protect condition on the column itself.
Generally speaking, try to do in PowerBuilder as much as you can WITHOUT script programming. U

Linking sidebarPanels in shiny for SelectizeInput function

Assume I have a drop down in sidebarPanel - location from which I can select a maximum of 2 options. I want to create an if loop where in - chosing 'Saddle Joint' and 'Gliding Joint' from the drop down leads to selection of objects 'x' and 'y' in another sidebarPanel - datasets - basically creating a linkage.
I tried this piece of code, but it doesn't work:
if (input$location== "Saddle Joint" & input$location== "Gliding Joint") {
updateCheckboxGroupInput(session,
"datasets", "Datasets:", choices = c("x","y"),
selected= c("x","y"))
}
Do take a look at the screenshot for better picture!
Thanks!
Screenshot
Issue was with the boolean in your if statement. Use this:
"Saddle Joint" %in% input$location & "Gliding Joint" %in% input$location
Also could use:
all(c("Saddle Joint","Gliding Joint") %in% input$location)

Scoping between output functions

I have been through (hopefully thoroughly enough) the shiny help article on scoping, and have also seen the answer regarding setting a global object here. Neither addresses, however, what I think (emphasis on "think") I need to do. If a variable is only created in an output function, can it be seen in another? Using action buttons, I'm trying to control lengthy calculations and some will only happen on condition of other things happening. As a minimal example,
library(shiny)
library(stringr)
fruitref <- c("apple","peach","pear","plum","banana","kiwi")
textareaInput <- function(inputID, label, value="", rows=10, columns=30) {
HTML(paste0('<div class="form-group shiny-input-container">
<label for="', inputID, '">', label,'</label>
<textarea id="', inputID, '" rows="', rows,'" cols="',
columns,'">', value, '</textarea></div>'))
}
ui <- fluidPage(titlePanel("minimal example"),
sidebarLayout(
sidebarPanel(
textareaInput("inputfruit", "Enter some fruits:"),
actionButton("checkfruit", "Check fruits"),
verbatimTextOutput("fruitstat")
),
mainPanel(
textOutput("fruits")
)
)
)
server <- function(input,output){
flag <- F
inputs <- eventReactive(input$checkfruit,{input$inputfruit})
continue <- reactive(flag)
output$fruitstat <- renderText({
inputs <- inputs()
inputs <- str_trim(unlist(strsplit(inputs,split="\n")),side="both")
if(length(setdiff(inputs,fruitref)) != 0 | length(inputs) == 0){
flag <- F
paste(paste(setdiff(inputs,fruitref), collapse=", "),"not in table.")
} else {
flag <- T
"All fruits ok."
}
})
output$fruits <- renderText({
paste("Continue? ",continue())
})
}
shinyApp(ui = ui, server = server)
There's a reference table and user input is checked against that table. User enters list in pieces until hitting the check button, then gets feedback whether all are OK, or if there's a mismatch. Only if all are okay do I want to continue. I tried setting a "continue" flag in the output function, but that didn't work, and setting it in the server outside of the output function would not update the value. I also tried creating an environment in the server function and using assign, but that too did not update the value when I tried to retrieve it for renderText later. Since it's not an input, accessible through input$, I figured I cannot use any of the update* functions.
This may not be the best way to set this kind of conditional. I saw in the tutorial the conditional pane, but that depends on an input, rather than something created in the function. More generally, there are more complicated objects to be created in the output functions (there will be four large tables and a plot at most; all or some subset will actually be output) that then other output functions should see, I did not think I could define them as reactive global objects, because until some later things happen, they can't be calculated.
Define continue as an eventReactive:
continue <- eventReactive(input$checkfruit, flag)
And also use the global assignment operator inside function
flag <<- F
flag <<- T
Then it will work. Tested.

Format mask for number field items: trailing and 'leading' zero

I'm having some trouble with displaying numbers in apex, but only when i fill them in through code. When numbers are fetched through an automated row fetch, they're fine!
Leading Zero
For example, i have a report where a user can click a link, which runs a javascript function. There i get detailed values for that record through an application process. The returned values are in JSON. Several fields are number fields.
My response looks as follows (fe):
{"AVAILABLE_STOCK": "15818", "WEIGHT": ".001", "VOLUME": ".00009", "BASIC_PRICE": ".06", "COST_PRICE": ".01"}
Already the numbers here 'not correct': values less than one do not have a zero before the .
I kind of hoped that the format mask on the items would catch this. If i specify FM999G990D000 for the item weight, i'd expect it to show '0.001' .
But okay, i suppose it only works that way when it comes through session state, and not when you set an item value through $("#").val() ?
Where do i go wrong? Is my only option to change my select in the app process?
Now:
SELECT '"AVAILABLE_STOCK": "' || AVAILABLE_STOCK ||'", '||
'"WEIGHT": "' || WEIGHT ||'", '||
'"VOLUME": "' || VOLUME ||'", '||
'"BASIC_PRICE": "' || BASIC_PRICE ||'", '||
Do i need to provide my numberfields a to_char with the format mask here (to_char(available_stock, 'FM999G990D000')) ?
Right now i need to put my numbers between quotes ofcourse, or i get invalid json when i parse it.
Trailing Zero
I have an application process on a page on the after header point, right after an automated row fetch. Several fields are calculated here (totals). The variables used are all specified as number(10, 2). All values are correct and rounded to 2 values after the comma. My format masks on the items are also specified as FM999G999G990D00.
However, when one of the calculated values has only one meaningfull value after the comma, the trailing zeros get dropped. Instead of '987.50', it is displayed as '987.5'.
So, i have a number variable, and assign it like this: :P12_NDB_TOTAL_INCL := v_totI;
Would i need to convert my numbers here too, with format mask?
What am i doing wrong, or what am i missing?
If you aren't doing math on it and are more concerned with formatting, I suggest treating it as a varchar/string instead of as a number wherever you can.