我正在使用HTML模板用于闪亮应用程序,并试图根据URI的片段标识符复制仪表板的tabPanel
功能。
具体来说,给定许多充当页面锚的导航链接,我希望Shiny可以使用该片段标识符,根据需要更新任何服务器端对象,然后返回与用户单击的任何伪-TAB相对应的输出。这是基于Joe Cheng的College College Corecard应用程序(只需将查询字符串换成页面锚)即可。我也宁愿不使用查询字符串走那个路线,因为该应用程序源于一个具有大量用户定义选择的较大数据集,这些选择必须在URI中编码。由于每个新搜索都会触发一个硬页面刷新,因此,每当您对输入进行较小的更改时,都可能不是一个不错的用户体验。
。我遇到的问题是,Shiny仅存储session$clientData
中的初始 uri hash,我没有办法强迫它更新(使用invalidateLater
,eventReactive
或observeEvent
)当用户从#summary
导航到#bleep
到#blorp
。有人遇到过类似问题吗?还是可以在没有硬页面刷新的情况下刷新session$clientData
对象?
另一个选项是,只需在display: none;
中添加一个新类,用于隐藏的Divs,然后写一点JS来处理事物。不过,理想情况下,我更喜欢找到一个基于闪亮的解决方案。
我的代码看起来与:
index.html:
...
<header role="banner">
<h3 class="usa-display">My header!</h3>
<ul>
<li><a class="nav active" href="#summary">Summary</a></li>
<li><a class="nav" href="#blorp">Another Tab</a></li>
</ul>
</header>
<div data-display-if="output.appMode === 'summary' ">
{{ renderVerbatimText("clientInfo") }}
</div>
<div data-display-if="output.appMode === 'blorp' ">
<img src="assets/img/failWhale.jpg" />
</div>
...
ui.r:
function(req) {
htmlTemplate(
"www/index.html"
)
}
server.r:
parseHashString <- function (str, nested = FALSE) {
if (is.null(str) || nchar(str) == 0) {
values <- "summary"
return(values)
}
if (substr(str, 1, 1) == "#") {
str <- substr(str, 2, nchar(str))
}
values <- strsplit(str, "#", fixed = TRUE)[[1]]
values <- values[!is.na(values)]
values <- values[values %in% c("summary", "blorp")]
return(values[1])
}
shinyServer(function(input, output, session) {
output$appMode <- reactive({
parseHashString(session$clientData$url_hash_initial)
})
outputOptions(output, "appMode", suspendWhenHidden = FALSE)
output$clientInfo<- renderText({
cdata <- session$clientData
cnames <- names(cdata)
allvalues <- lapply(cnames, function(name) {
paste(name, cdata[[name]], sep=" = ")
})
paste(allvalues, collapse = "n")
})
})
我最终通过创建自定义闪亮输入来弄清楚这一点。基本上,我刚刚创建了一个空/隐藏的Div来反映新的光泽输入。最重要的是,根据Rstudio的说明,这只是一个非常标准的输入绑定。我必须进行的唯一修改是在URI哈希更改时触发回调(在这种情况下,在用户单击任何NAV链接之后)。导航单击触发on("hashchange" function() {...})
,然后迫使input$appHash
更新。无论我在server.R
中拥有的任何逻辑并可以有条件地显示出任何新的URI哈希。
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
{{ headContent() }}
{{ bootstrapLib() }}
<script>
$(document).ready(function(){
var hashBinding = new Shiny.InputBinding();
$.extend(hashBinding, {
find: function(scope) {
return $(scope).find(".appHash");
},
getValue: function(el) {
return $(el).val();
},
setValue: function(el, value) {
$(el).val(value);
},
subscribe: function(el, callback) {
$(el).on("change.hashBinding", function(e) {
$(el).val(window.location.hash);
callback();
});
},
unsubscribe: function(el) {
$(el).off(".hashBinding");
}
});
Shiny.inputBindings.register(hashBinding);
$('.nav').click(function () {
$('.nav').removeClass('active');
$(this).addClass('active');
});
$(window).on('hashchange', function() {
var el = $(".appHash");
el.trigger("change");
});
});
</script>
</head>
<body>
<header role="banner">
<div class="appHash" id="appHash" style="display:none;"></div>
<ul>
<li><a class="nav active" href="#summary">Summary</a></li>
<li><a class="nav" href="#bleep">Tab X</a></li>
<li><a class="nav" href="#blorp">Tab Y</a></li>
<li><a class="nav" href="#faq">F.A.Q.</a></li>
</ul>
</header>
</body>
</html>