Code Monkey home page Code Monkey logo

shinymatrix's Introduction

Matrix Input for Shiny

R-CMD-check Coverage Status CRAN status

Matrix Input for Shiny

This package provides an input field to enter matrix conveniently in a shiny application. It supports tabbing and jumping linewise in the matrix.

Screenshot Simple Matrix

Installation

From CRAN:

install.packages("shinyMatrix")

From GitHub:

if (require("devtools")) install_github("INWTlab/shiny-matrix")

Usage

UI

The input field is generated by the function matrixInput

matrixInput <- function(inputId,
                        value = matrix("", 1, 1),
                        inputClass = "",
                        rows = list(),
                        cols = list(),
                        class = "character"
                        pagination = FALSE,
                        lazy = FALSE){
  [...]
}

You can define parameters as follows:

Parameter Description
inputId id of html element
value matrix
inputClass class of html element (Class matrix-input is added automatically)
rows list of parameters (see below)
cols list of parameters (see below)
class class of resulting matrix (numeric and character) is supported
pagination Should the matrix be paginated (10 rows per page)
lazy Lazy update data on server

Parameter rows / cols take a list of arguments. The following is supported

Parameter Description
n number of rows (is calculated from value per default)
names show row/colnames (names are taken from value)
editableNames should row/colnames be editable?
extend should rows/cols be automatically be added if table is filled to the last row / column?
delta how many blank rows/cols should be added
multiheader Display multiheader - currently only header spanning two columns are supported

Call the matrixInput function in your UI generating, e.g. ui.R

## numeric matrix
matrixInput("matrix1", class = "numeric")

## editable rownames
matrixInput("matrix2",
  rows = list(
    names = TRUE,
    editableNames = TRUE),
  data = matrix(letters[1:12], 3, 4)
)

Get value

You can access the value from the matrix input using input$inputId in your server function. The result will always be a matrix of the class defined in matrixInput.

Update Input Field

You can update the input field using updateMatrixInput

updateMatrixInput(session, inputId, value = NULL)

value is the data object. In the future there should be also support to update the other parameters.

Example Apps

You find the code for the example app in inst/appXXX.

Basic functionality

  • Fixed matrix width
  • Editable matrix content
  • No column and rownames

Use the matrix on the left to input values, matrix on the right displays the result.

library(shinyMatrix)

startApplication("app")

Update Matrix Input from R

  • Generate a random matrix within the shiny server function by clicking on "Update Matrix"
  • The matrixInput field gets updated with updateMatrixInput from R
startApplication("appUpdate")

Editable row and column names

  • Edit row and column names by clicking on the cell
  • The result will be shown on the right
startApplication("appRownames")

Uneditable cells

  • Make table cells uneditable
  • No clicking into cells, no changing values
startApplication("appUneditableCells")

Extend Matrix Automatically

  • If matrix is full (last row and columns contain values) rows and columns are added automatically
startApplication("appExtend")

Custom Column Header

  • Replace default header with a multiheader
  • Automatically add 2 columns if matrix is full
startApplication("appDoubleHeader")

Delete Rows and Columns

  • add a button to delete rows and columns. This also works for multiheader.
startApplication("appDelete")

Lazy Update of server values

  • Only update data on server when no input field is visible
startApplication("appLazy")

shinymatrix's People

Contributors

aneudecker avatar jan-abel-inwt avatar chamaoskurumi avatar sarahwagner avatar wahani avatar jassler avatar

Stargazers

Anna avatar Jared Knowles avatar George Mwangi avatar  avatar Andrew Allen Bruce avatar Sean Coffey avatar  avatar  avatar Srikanth K S avatar  avatar Dong avatar KenWWW avatar  avatar Alex Ho avatar Victor Perrier avatar Rui avatar Juha Lehtiranta avatar Jimmy Briggs avatar Felipe Mattioni Maturana, Ph.D. avatar

Watchers

James Cloos avatar  avatar Amit Ghosh avatar Jonathan avatar  avatar Antonia Runge avatar

shinymatrix's Issues

Copy and pasting between Excel and shinyInput

The documentation for shinyMatrix states that one can copy and paste data from table applications into an app using shinyMatrix. However, I appear to be unable to do so. With the app, the code of which is provided below, I am unable to copy and paste ranges of cells between Excel and the shiny app. I couldn't find any arguments in the help page for shinyInput to enable copy and pasting. Am I misunderstanding how copy and paste should work, or am I doing something wrong? I would appreciate any guidance.

library("shinyMatrix") 
m <- matrix(rep(0.0025, 4), nrow = 2,
              dimnames = list(c("A","B"), c("A","B")))
ui <- fluidPage(sidebarPanel(width = 6, 
                             matrixInput("sample", 
                                         value = m,
                                         label = "Paste your data below:",
                                         class = "numeric")))
server <- function(input, output, session) {
  #intentionally empty
  } 
shinyApp(ui, server)

Control number of decimals

Hello,

I think it would be nice to have the possibility to control the number of decimals of the displayed numeric cell values.

I don't know Vue, but maybe:

<span v-else>{{ value.toFixed(ndigits) }}</span>

The number of digits for each cell could be given as an option in a matrix.

Moving between cells and editing

I really like your package but have two comments:

  1. When navigating between the cells of the matrix the use of the arrow keys (up, down, left right) seems much more natural to me than using the combinations "shift enter" or "shift tab".
  2. Since interactive input of matrix elements is the intended usage of the package I would expect that after navigating to a new cell this new cell is not only focused but also the current value selected so that a new value can be inserted immediately.

matrixInput: row names affect matrix extensibility

The following example, where the row names are set to TRUE works perfectly, i.e. the matrix extends as I add data.

 matrixInput(
                 inputId = "dataMatrix",
                 class = "numeric",
                 value = matrix(),
                 copy = TRUE,
                 paste = TRUE,
                 cols = list(
                   names = TRUE,
                   extend = TRUE,
                   delta = 1,
                   editableNames = TRUE
                 ),
                 rows = list(
                   names = TRUE,
                   editableNames = TRUE,
                   extend = TRUE,
                   delta = 1
                 ) 
               )

As I change the name option in rows to FALSE, the matrix does not extend anymore.

 matrixInput(
                 inputId = "dataMatrix",
                 class = "numeric",
                 value = matrix(),
                 copy = TRUE,
                 paste = TRUE,
                 cols = list(
                   names = TRUE,
                   extend = TRUE,
                   delta = 1,
                   editableNames = TRUE
                 ),
                 rows = list(
                   names = FALSE,
                   editableNames = TRUE,
                   extend = TRUE,
                   delta = 1
                 ) 
               )

`.vue-input td` class seems to overrule border-left and border-top attribute

I have the following example:

slibrary(shiny)

ui <- fluidPage(
  tags$style('#mat td, #mat th { border-left: 1px solid red; border-top: 1px solid red; }'),
  shinyMatrix::matrixInput(
    'mat', value = matrix(1:20, nrow = 4)
  )
)

server <- function(input, output, session) {}

shinyApp(ui, server)

From this I would assume that for each table cell its left and top border are marked red. However this applies only for the outermost border to the left and to the top.

image

I was able to get the expected behavior when disabling the border attribute of .vue-input td in the developer tools.

image

Overall setting borders seems a little inconsistent to me. For instance how would I go about making every border invisible except for a specific cell?

Can't set rows.names as FALSE on v0.5.0

Hi! Thank you for the package, it's been really helpful.

Apart from the broken table style (#18), I found that

shinyMatrix::matrixInput(
  ...,
  rows = list(names = FALSE)
)

doesn't work on the 0.5.0 release, as the rownames are always displayed.

I checked on the 0.4.0 (d79f887), and the names parameter works as expected.

Thanks 😃

Enforcing input restrictions

Hi,

Do you know how I would be able to go about applying input rules (e.g. every row must sum to 1, no negative numbers, etc.)?

Great package. Thanks!

Input only shown when clicking on next cell, but not when using Tab or enter

Hi,

I've got a question: I implemented shiny-matrix in my app and it's a really great extension. I've got one question though: When I enter a value in the matrix, the entered value is only shown when I click on the next cell but not when I use Tab or Enter. Is there a way to fix this? If that is not possible, would it be possible to prevent the user from using "Tab" or "Enter" while working on the matrix?

Thanks in advance!

recordTest does not work with matrixInput

recordTest does not work with shinyMatrix

Not sure if this belongs here or at shinytest. Cross-posted as issue #311.

I've run in to a problem when I try to use shinytest to test an app where I use shinyMatrix's matrixInput. To reproduce, I've taken the following example app from the GitHub repo:

ui.R:

library(shinyMatrix)

m <- diag(5)
# colnames(m) <- 1:3
# rownames(m) <- letters[1:3]

shiny::tagList(
  shiny::fluidPage(
    shiny::titlePanel("Demonstration Matrix Input Field"),
    shiny::fluidRow(
      column(6, matrixInput(
        inputId = "matrix",
        value = m,
        class = "numeric",
        cols = list(
          names = TRUE
        ),
        rows = list(
          names = TRUE
        )
      )),
      column(6, tableOutput("table"))
    )
  )
)

and server.R:

library(shinyMatrix)

function(input, output, session) {
  output$table <- renderTable(input$matrix, rownames = TRUE)
}

I then record a test where I just change a number in the input matrix:

> library(shinytest)
> recordTest()

This gives the following console output:

Loading required package: shiny

Listening on http://127.0.0.1:5017
C> Running application in test mode.
C> Loading required package: shiny
C> 
C> Listening on http://127.0.0.1:7857
Saved test code to /home/simen/repos/shinymatrixshinytestissue/tests/mytest.R
Running mytest.R Error in session_makeRequest(self, private, endpoint, data, params, headers) : 
  undefined is not an object (evaluating 'value.data.length')

The recorded snapshot looks like this:

001

When I try to run the test, I get error message at the end again:

> testApp()
Running mytest.R Error in session_makeRequest(self, private, endpoint, data, params, headers) : 
  undefined is not an object (evaluating 'value.data.length')

I've tried to run it in debug mode, but I don't understand what happens in the JavaScript at line 12 in the traceback from the call above:

> traceback()
17: stop(create_condition(response, "error", call = call))
16: report_error(response)
15: session_makeRequest(self, private, endpoint, data, params, headers)
14: private$makeRequest("EXECUTE ASYNC SCRIPT", list(script = script, 
        args = args))
13: session_executeScriptAsync(self, private, script, ...)
12: private$web$executeScriptAsync("var wait = arguments[0];\n    var timeout = arguments[1];\n    var callback = arguments[2];\n    shinytest.outputValuesWaiter.start(timeout);\n    shinytest.inputQueue.flush();\n    shinytest.outputValuesWaiter.finish(wait, callback);", 
        wait, timeout)
11: sd_flushInputs(self, private, wait, timeout)
10: private$flushInputs(wait_, timeout_)
9: sd_setInputs(self, private, ..., wait_ = wait_, values_ = values_, 
       timeout_ = timeout_, allowInputNoBinding_ = allowInputNoBinding_, 
       priority_ = priority_)
8: app$setInputs(matrix = c(c("1", "0", "0", "0", "0"), c("0", "1", 
       "0", "0", "0"), c("0", "0", "1", "0", "0"), c("0", "0", "0", 
       "1", "0"), c("0", "0", "0", "1", "1"), "", "", "", "", "", 
       "", "", "", "", "")) at mytest.R#5
7: eval(ei, envir)
6: eval(ei, envir)
5: withVisible(eval(ei, envir))
4: source(testname, local = env)
3: FUN(X[[i]], ...)
2: lapply(found_testnames, function(testname) {
       withr::local_dir(testsDir)
       withr::local_envvar(c(RSTUDIO = ""))
       withr::local_options(list(shinytest.app.dir = "appdir"))
       gc()
       env <- new.env(parent = .GlobalEnv)
       if (!quiet) {
           message(testname, " ", appendLF = FALSE)
       }
       source(testname, local = env)
   })
1: testApp()

My guess is that there is something strange going on in the app$setInput call on line 8, so maybe the input to the matrix was not parsed correctly in recordTest? Here is the generated mytest.R where the app$setInput happens:

app <- ShinyDriver$new("../")
app$snapshotInit("mytest")

app$snapshot()
app$setInputs(matrix = c(c("1", "0", "0", "0", "0"), c("0", "1", "0", "0", "0"), c("0", "0", "1", "0", "0"), c("0", "0", "0", "1", "0"), c("0", "0", "0", "1", "1"), "", "", "", "", "", "", "", "", "", ""))
app$snapshot()

How to adjust input matrix column width, and background colors?

Hello, I have a 2-part question regarding formatting/styling:

  1. Is there a way to adjust the width of a specific column in the input matrix? In particular I'm trying to adjust the width of the row label column (left-most column with row labels). But if possible I'd like to know how to adjust the width of any specified column.
  2. Is there a way to specify the background colors of a specified column in the input matrix?

Thank you!

More of a question than issue: how to hide row header column in shinyMatrix?

Hi! When generating an input matrix, is it possible to hide or eliminate the left-most column for row headers? If not possible, are there other ways to adjust it (obfuscate it) by other means such as narrowing, filling in with color, etc.?

Below is simple R code that generates the matrix pictured at the bottom:

library(shiny)
library(shinyMatrix)

m <- matrix(runif(12), 6, 2, dimnames = list(NULL, c("x", "y"))) 
ui <- fluidPage(   
  titlePanel("shinyMatrix: Simple App"),   
  sidebarPanel(     
    width = 6,     
    tags$h4("Input matrix"),     
    matrixInput("sample",value = m,rows = list(extend = TRUE),cols = list(names = TRUE))
    ),   
  mainPanel(     
    width = 6,plotOutput("scatter")) 
  ) 

server <- function(input, output, session) {   
  output$scatter <- renderPlot({     
    plot(input$sample, col = "red", main = "Scatterplot")}) 
  } 

shinyApp(ui, server)

And now the output image:

shinyMatrix

Matrix becomes uneditable with non-extendable cols

The appExtendNoNames example works perfectly.

However, if I change extend = TRUE to extend = FALSE on line 16, any cells to the right of a cell I edit become uneditable.

Video demonstration:
https://user-images.githubusercontent.com/8095080/188219333-f275ab0a-dd8f-49a9-a2a9-7ef1e234f529.mov

Full code:

library(shiny)
library(shinyMatrix)

m <- diag(3)
# colnames(m) <- 1:3
# rownames(m) <- letters[1:3]

ui <- shiny::tagList(
  shiny::fluidPage(
    shiny::titlePanel("Demonstration Matrix Input Field"),
    matrixInput(
      inputId = "matrix",
      value = m,
      class = "numeric",
      cols = list(
        names = FALSE,
        extend = FALSE
      ),
      rows = list(
        names = FALSE,
        extend = TRUE,
        delta = 1
      )
    )
  )
)

server <- function(input, output, session) {
  output$table <- renderTable(input$matrix, rownames = TRUE)
}

shinyApp(ui = ui, server = server)

How to Read the individual elements of the matrix

Hi,
I was trying to read the elements of the matrix, that i created using matrixInput.
I was getting an error to use reactive elements or event handler, but even after not able to extract the element of matrix.

Same is working if i am using render table.

Can you help on this?

Thanks
Satendra

Usage in flexdashboard and runtime shiny

Hi all, I'm totally new to this package and it is something I was looking for for a while.

I found this article:
https://www.r-bloggers.com/shinymatrix-matrix-input-for-shiny-apps/
and used the code to build the app.R file and it worked perfectly fine.

Usually I use flexdashboards with the shiny runtime. I tried to use the same code but was not able to get it running. Please find a minimal example below.

Any help is much appreciated.

Thanks Dirk

---
title: "shinyMatrix Package"
output: 
  flexdashboard::flex_dashboard:
runtime: shiny
---

```{r global, include = FALSE}

library(shinyMatrix) # https://github.com/INWTlab/shiny-matrix

Sidebar {.sidebar}

Matrix


m <- matrix(runif(12), 6, 2, dimnames = list(NULL, c("x", "y")))

matrixInput(
  inputId = "sample", 
  value = m,
  #inputClass = matrix-input,
  rows = list(extend = TRUE), 
  cols = list(names = TRUE),
  class = "numeric",
  paste = TRUE,
  copy = TRUE
)

Matrix

Column

Display Plot


renderPlot({
  plot(input$sample, col = "red", main = "Scatterplot")
})

Change or disable click behavior

As far as I understand it, when I click a cell, a class active is added to the td element, which adds an input element to the cell until something outside of the matrix is clicked.

Is it possible to change or even completely disable this behavior? I.e., if I only want to display static content, I don't want users to be confused if nothing happens when they change some values. Or, I want some other R function (alternatively just any other js function) to execute when a user clicks on a cell.

Is that possible?

How to add automatic sequential row/column headers for shiny Matrix when it is extendable?

When setting row and/or column to extend = TRUE in the matrixInput function, how do you generate automatic, sequential row and/or column headers? For example, each added column would be labeled A, B, C, D, etc., or Series A, Series B, Series C, etc., or 1, 2, 3, 4, etc.

In reviewing the package documentation I found a reference: createHeader, updateHeader -- name of javascript function to override default function to create/update table header. The function needs to have the table element and the data object as argument. This may be the path I need (???) to take but I am unable to find working examples.

Bug when using extend feature for rows in the matrix

UPDATE 03 June 2023: this bug still persists in version 6.0. However a hackish workaround is setting matrix columns extend to TRUE even if you don't need to extend columns, and set the extension delta to 0, like this: matrixInput(... cols = list(extend = TRUE, delta = 0, ...) ...). This takes care of the problem for me.

Hi, shinyMatrix really fits my needs. Thank you for this! Perhaps I´m not using the app correctly, or maybe it´s a bug. But when I use the extend feature for inserting additional rows into a matrix, it only works if I click on the right-most field of the new row. If I click on any other field (to the left of the right-most) of the new row, then the matrix is left with invalid fields in that row and there´s no way to go back and fix it other than starting all over again. Below is the code I´m using. I also screen shot an example of what happens when I click on any column other than the right-most: a successful row insertion is shown in blue, an unsuccessful row insertion shown in red.

library(shinyMatrix)
m <- diag(5)
colnames(m) <- 1:5
rownames(m) <- letters[1:5]

ui <- fluidPage(
        titlePanel("Demonstration Matrix Input Field"),
        fluidRow(
          column(6, matrixInput(
                      inputId = "matrix",
                      label = "Default matrix",
                      value = m,
                      class = "numeric",
                      cols = list(names = TRUE),
                      rows = list(extend = TRUE,names = TRUE) # change "extend" to TRUE
                    )
          ),
          column(6, tableOutput("table"))
        )
      )

server <- function(input, output, session) {
            output$table <- renderTable(input$matrix, rownames = TRUE)
          }

shinyApp(ui, server)

Attached image:
shinyMatrix

Deployment of R-Package to INWTlab drat Repo

We are currently not automatically deploying the R-package to the INWTlab drat repository. While there is a travis.yaml file present, indicating that Travis was previously utilized, I plan to transition the package deployment to a GitHub Actions workflow.

Styling not working for ShinyMatrix

Hello!

I have not been able to get shiny-matrix to display in the proper stylized format with grid lines and such.

I have provided a simple example program I found on the internet, which seems to load fine in the example, and a screenshot of how the application looks when I load it on my computer.

Screen Shot 2021-04-15 at 6 06 53 PM

Any help would be greatly appreciated.

Thanks!

-Clay

app.R.zip

tab not catched to move across controls

In general, if you press tab, you are going to move to the next control in the UI. However, this does not happen with shinyMatrix. If the matrix is not focused, you can't focus it pressing tab from a previous control. If the matrix is focused, you can't leave it by pressing tab.

The expected behavior is to be able to focus in and focus out using tab, and therefore triggering store of the changed data on focus out (as if you were clicking outside with the mouse)

Can this package support an upper triangular matrix input?

Thanks for creating this package, and I found it is very useful. I intended to use this matrix input to collect variance-covariance components as user input. As the variance-covariance matrix is symmetric, which means I only need the upper triangle rather than the whole matrix input. I was wondering if this package supports an upper triangular matrix input?

Fail to install

Unable to install the package from CRAN:

install.packages("shinyMatrix") returns:

Installing package into ‘C:/Users/jgomez/Documents/R/win-library/3.5’
(as ‘lib’ is unspecified)
Warning in install.packages :
package ‘shinyMatrix’ is not available (for R version 3.5.1)
Warning in install.packages :
unable to access index for repository http://www.stats.ox.ac.uk/pub/RWin/bin/windows/contrib/3.5:
cannot open URL 'http://www.stats.ox.ac.uk/pub/RWin/bin/windows/contrib/3.5/PACKAGES'

Also, when I tried with his one: if (require("devtools")) install_github("INWTlab/shinyMatrix"), the result was also an error:

Downloading GitHub repo INWTlab/shinyMatrix@master
from URL https://api.github.com/repos/INWTlab/shinyMatrix/zipball/master
Installation failed: Not Found (404)

Q: Possible to apply formatting to input?

Hi, thanks for the great package.

My question is whether the inputs can be styled.

Ex. A user inputs 1365845, which is styled as 1,365,845.00 after the user inputs it?

Do you have an idea how to do this?

Thanks again.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.