From 08c32fe76882db4902e9758ff1317537a44a96cf Mon Sep 17 00:00:00 2001 From: Carson Date: Wed, 21 May 2025 18:26:04 -0500 Subject: [PATCH 1/2] More generally ensure Shiny.OutputBinding.renderValue() doesn't produce multiple widget views on a given element --- js/src/output.ts | 8 ++++++++ shinywidgets/static/output.js | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/js/src/output.ts b/js/src/output.ts index 8ace1d6..02e6ea7 100644 --- a/js/src/output.ts +++ b/js/src/output.ts @@ -103,6 +103,14 @@ class IPyWidgetOutput extends Shiny.OutputBinding { const view = await manager.create_view(model, {}); await manager.display_view(view, {el: el}); + // Don't allow more than one .lmWidget container, which can happen + // when the view is displayed more than once + // N.B. It's probably better to get view(s) from m.views and .remove() them, + // but empirically, this seems to work better + while (el.childNodes.length > 1) { + el.removeChild(el.childNodes[0]); + } + // The ipywidgets container (.lmWidget) const lmWidget = el.children[0] as HTMLElement; diff --git a/shinywidgets/static/output.js b/shinywidgets/static/output.js index 3c8e298..afa2344 100644 --- a/shinywidgets/static/output.js +++ b/shinywidgets/static/output.js @@ -36,7 +36,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac \***********************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _jupyter_widgets_html_manager__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyter-widgets/html-manager */ \"@jupyter-widgets/html-manager\");\n/* harmony import */ var _jupyter_widgets_html_manager__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyter_widgets_html_manager__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _comm__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./comm */ \"./src/comm.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\nvar _a;\n\n\n\n/******************************************************************************\n * Define a custom HTMLManager for use with Shiny\n ******************************************************************************/\nclass OutputManager extends _jupyter_widgets_html_manager__WEBPACK_IMPORTED_MODULE_0__.HTMLManager {\n // In a soon-to-be-released version of @jupyter-widgets/html-manager,\n // display_view()'s first \"dummy\" argument will be removed... this shim simply\n // makes it so that our manager can work with either version\n // https://github.com/jupyter-widgets/ipywidgets/commit/159bbe4#diff-45c126b24c3c43d2cee5313364805c025e911c4721d45ff8a68356a215bfb6c8R42-R43\n async display_view(view, options) {\n const n_args = super.display_view.length;\n if (n_args === 3) {\n return super.display_view({}, view, options);\n }\n else {\n // @ts-ignore\n return super.display_view(view, options);\n }\n }\n}\n// Define our own custom module loader for Shiny\nconst shinyRequireLoader = async function (moduleName, moduleVersion) {\n // shiny provides a shim of require.js which allows