В приложении RStudio, выполненном с использованием таблицы renderTable()
, я хотел бы добавить ведущий столбец переключателей (реактивный, конечно) и изменить стиль выбранного ряд. Какая стратегия? Я думаю, что я могу использовать jQuery, если это абсолютно необходимо, но нет ли более простого способа? Я пробовал вставлять html в ячейки таблицы в выражениях renderTable()
... не работает.в RStudio блестящий, желающий настроить таблицу
ответ
Преследуя @MadScone «s отличный совет, я придумал следующий код, который является окончательным решением
Некоторые дополнительные особенности, которые делают его работу для меня являются: * радио-кнопки в колонке 1 (не строка 1) * они принадлежат к одной и той же группе радиосвязи * строка заголовка таблицы правильно отформатирована * строка, выбранная переключателем, получает специальное форматирование без необходимости jQuery.
values = reactiveValues(PopRow=1) ### To receive and hold the selected row number.
f.objects_table_for_OneCT = function(){
f.changeSelectedRow() #### See definition below.
df = createObjectsTable() #### Any data frame goes here; code not provided here.
selectedRow = values$PopRow
header_html <- function(table_cell) paste0('<th>', table_cell, '</th>')
cell_html <- function(table_cell) paste0('<td>', table_cell, '</td>')
radio_html <- function(radio_name, radio_value, is_checked, radio_text) {
paste0('<input type="radio" name="',
radio_name, '" value=', radio_value,
ifelse(is_checked, " checked ", ""),
'>', radio_text)
}
row_html <- function(table_row_num) {
table_row = df[table_row_num, ]
cells <- sapply(table_row, cell_html)
cells <- c(cell_html(radio_html(
"whichRow", table_row_num, table_row_num == selectedRow, "")),
cells)
collapse_cells <- paste0(cells, collapse='')
selectedRowStyle = "style='color:red; font-weight:bold'"
collapse_cells <- paste0('<tr ',
ifelse(table_row_num == selectedRow, selectedRowStyle, ""),
'>', collapse_cells, '</tr>')
collapse_cells
}
df_rows <- sapply(1:nrow(df), row_html)
df_header_row <- header_html(c("CHOICE", names(df)))
collapse_cells <- paste0(c(df_header_row, df_rows), collapse='')
full_table <- paste0('<table class=\"data table table-bordered table-condensed\">',
collapse_cells, '</table>')
return(full_table)
}
output$objects_table_for_OneCT = renderText({f.objects_table_for_OneCT()})
(Что касается последней строки, я обычно обернуть expr
ARG в функции, так что я могу debug
. До сих пор это работало нормально.)
Функция, которая реагирует на кнопки радио выглядит следующим образом :
f.changeSelectedRow = reactive({
if(is.null(values$PopRow)) values$PopRow = 1
if(!is.null(input$whichRow)) ### from the radio button set.
if(input$whichRow != values$PopRow) values$PopRow = input$whichRow
})
Не уверен, что вы все еще ищете ответ на этот вопрос. Наверное, нет, но мне грустно видеть, что она не ответила. Я бы просто создал таблицу html самостоятельно и использовал renderText()
.
В качестве примера, скажем, вы хотите этот кадр данных на странице с радио-кнопки в верхнем ряду:
df <- data.frame(A=1:5, B=1:5)
Сначала нужно, чтобы превратить df
в HTML-таблицу. Вот функции, чтобы сделать HTML ячеек таблицы и строки:
cell_html <- function(table_cell) paste0('<td>', table_cell, '</td>')
row_html <- function(table_row) {
cells <- sapply(table_row, cell_html)
collapse_cells <- paste0(cells, collapse='')
paste0('<tr>', collapse_cells, '</tr>')
}
И с помощью этих функций:
df_rows <- apply(df, 1, row_html)
Теперь вот глупая функция, чтобы сделать радио-кнопки:
radio_html <- function(radio_name, radio_value, radio_text) {
paste0('<input type="radio" name="',
radio_name, '" value="', radio_value, '">', radio_text)
}
Давайте сделаем так многие радиокнопки, так как есть столбцы в df
:
radios <- sapply(seq_along(df),
function(x) radio_html(paste0('row', x), x, paste(x)))
Это будет производить HTML формы:
<input type="radio" name="row1" value="1">1
Для каждой строки. Затем бросить radios
в row_html
сделать HTML строку таблицы из них:
radio_row <- row_html(radios)
Теперь нам нужно объединить df
, радио-кнопки и обернуть все это в таблице тегов HTML.
table_cells <- c(radio_row, df_rows)
collapse_cells <- paste0(table_cells, collapse='')
full_table <- paste0('<table>', collapse_cells, '</table>')
Поместите это целое зверя в функцию renderText()
. Я не уверен, что вы используете ui.R
или свой собственный интерфейс HTML. Я всегда делаю последнее, это дает вам гораздо больше свободы. Я бы это на моей странице:
<div name="x" id="x" class="shiny-html-output"></div>
Оказать свою таблицу output$x
. Чтобы создать выбранную строку, я бы рекомендовал использовать jQuery. Простое событие вдоль линий (сильно непроверенного) [EDIT: см предложенной поправки в комментариях ниже]:
$('table input:radio').change(function() {
var index = $('#table input:radio').index(this);
// Add one to skip radio button row.
$('table tr').eq(index + 1).css('background-color', 'blue');
// Also handle reset on other rows
// ...
// ...
});
в качестве альтернативы Вы можете попробовать и построить таблицу и «выбранный» класс в соответствующую строку таблицы на стороне сервера, с некоторыми CSS готовы его стиль.
В отсутствие данных выборки все это не проверено, поэтому ожидайте некоторые ошибки.
Кроме того, если вы счастливы использовать ui.R
, а не свой собственный HTML-код, этот метод все равно должен работать. Я просто предлагаю использовать пользовательский HTML, как вы, кажется, блуждаете по этому маршруту.
Я отвечал на то, что вы просили ... т. Е. Сделать ведущий ряд переключателей. Я, вероятно, не сделал бы этого сам. Почему бы не просто создать свой стол в обычном режиме с renderTable()
и добавить в него переключатели отдельно, т. Е. Вообще не часть таблицы? Для получения справки см. this page of the Shiny tutorial. Если вам абсолютно необходимо выровнять переключатели со столбцами таблицы, это может быть достигнуто с помощью некоторого CSSing.
Незначительный, но важный момент, я бы изменил '$ ('table input: radio'). Change (function() {' to '$ (document) .on ('change', 'table input : radio ', function() {', поскольку последний позволит продолжить работу после того, как таблица будет заново создана сервером (т.е. каждый раз, когда' ren выполняется код derText'). В основном он будет прослушивать событие изменения во всех будущих экземплярах 'table input: radio', а не только те, которые существуют во время выполнения этой строки. –
Хороший вопрос Джо, это то, что вызывало у меня проблемы в последнее время. – MadScone
Спасибо! Это то, что я искал. Очень ценится. – Roger
Чтобы уточнить, нужен ли источник данных для df также реактивный? –