我正在为一个Shiny应用程序使用HTML模板,并且我正在尝试复制仪表板' tabPanel
基于URI的片段标识符的功能。
具体来说,鉴于许多导航链接充当页面锚点,我希望Shiny获取该片段标识符,根据需要更新任何服务器端对象,并返回与用户单击的任何伪标签对应的输出。这是基于Joe Cheng的college scorecard application(只需换出页面锚点的查询字符串)。我还不愿意使用查询字符串来访问该路由,因为该应用程序使用大量用户定义的选择来源更大的数据集,这些选择必须在URI中进行编码。由于每次新搜索都会触发硬页面刷新,因此每当您对输入进行微小更改时,这可能会导致数据重新加载,预处理等用户体验不佳。
我遇到的问题是,Shiny只会在session$clientData
中存储初始 URI哈希值,并且我发现没有任何方法可以强制使用要在用户从invalidateLater
导航到eventReactive
到observeEvent
时更新(使用#summary
,#bleep
或#blorp
)。有没有人遇到过类似的问题?或者是否可以在没有硬页面刷新的情况下刷新session$clientData
对象?
另一种选择是只用display: none;
为隐藏的div添加一个新类到CSS,并编写一些JS来处理事情。但理想情况下,我更愿意找到一种基于Shiny的解决方案。
我的代码类似于:
的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")
})
})
答案 0 :(得分:0)
我最终通过创建自定义Shiny输入来解决这个问题。基本上我只是创建了一个空/隐藏div来反映新的Shiny输入。最重要的是每个Rstudio's instructions只是一个非常标准的输入绑定。我必须做的唯一修改是在URI哈希改变时触发回调(在这种情况下,在用户点击任何导航链接之后)。导航点击会触发on("hashchange" function() {...})
,然后强制input$appHash
进行更新。无论新的URI哈希是什么,我都会在server.R
中遵守任何逻辑,并且可以有条件地显示输出。
<强>的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>