R-在Shiny $ ClientData中更新Shiny中的片段标识符



我正在使用HTML模板用于闪亮应用程序,并试图根据URI的片段标识符复制仪表板的tabPanel功能。

具体来说,给定许多充当页面锚的导航链接,我希望Shiny可以使用该片段标识符,根据需要更新任何服务器端对象,然后返回与用户单击的任何伪-TAB相对应的输出。这是基于Joe Cheng的College College Corecard应用程序(只需将查询字符串换成页面锚)即可。我也宁愿不使用查询字符串走那个路线,因为该应用程序源于一个具有大量用户定义选择的较大数据集,这些选择必须在URI中编码。由于每个新搜索都会触发一个硬页面刷新,因此,每当您对输入进行较小的更改时,都可能不是一个不错的用户体验。

我遇到的问题是,Shiny仅存储session$clientData中的初始 uri hash,我没有办法强迫它更新(使用invalidateLatereventReactiveobserveEvent)当用户从#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>

最新更新