Hi there,
Components are sandboxed to iframes and the default policies are listed in this file. The allow-top-navigation
is not part of them. Without this, it is not possible to have links in components that open a link (for instance in other page of the streamlit app) using the current tab (meaning with href="_top"
or href="_parent"
.
Is it possible to modify this restriction? I found this answer but it is a bit hacky as it uses javascript to directly update the attributes of the sandbox.
Hey @Melaine,
Thanks for sharing this question! I’d recommend posting this in GitHub Issues as a formal enhancement request so our product/engineering teams can take a look!
Hello @Melaine did you achieve any success related to this issue?
Facing the same thing here.
Best!
Hi @MarcosBerghahn,
I used the hacky solution using javascript. This post was useful. In my codebase it all boiled down to calling this python function on scripts for which I have this issue. I know it is hacky and ugly but I was in a rush
def allow_top_navigation():
''' Allow links embedded in iframes to open in the same tab (target='_parent' or '_top')
Useful for links in AgGrid grids
'''
# I know... This is ugly...
# Waiting for next versions of Streamlit when there will be more control over iframes
# or maybe with better tables in order to get rid of AG Grid altogether
# Refer to http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/
st.components.v1.html('''<script language="javascript">
// The document will listen to all 'animationstart' events and some of which have been named 'nodeInserted' by a css trick
var updateAndReloadIframes = function () {
var reloadRequired = false;
// Grab all iFrames from agGrid, add the 'allow-top-navigation' property and reload them
var iframes = parent.document.querySelectorAll("iframe[title='st_aggrid.agGrid']");
for (var i = 0; i < iframes.length; i++) {
if (!iframe.sandbox.contains('allow-top-navigation')) {
reloadRequired = true;
iframes[i].setAttribute("sandbox", "allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads allow-top-navigation-by-user-activation allow-top-navigation");
}
}
if (reloadRequired) {
setTimeout(function() {
for (var i = 0; i < iframes.length; i++) {
iframes[i].contentWindow.location.reload();
}
}, 300)
}
}
var event = function(event){
if (event.animationName == 'nodeInserted') updateAndReloadIframes()
}
parent.document.addEventListener('animationstart', event, false);
parent.document.addEventListener('MSAnimationStart', event, false);
parent.document.addEventListener('webkitAnimationStart', event, false);
// Some weird bug appear in prod env. Fix: ping the DOM every 1 second to add the property to the iframes if necessary
var intervalId = window.setInterval(function(){
var reloadRequired = false;
parent.document.querySelectorAll("iframe[title='st_aggrid.agGrid']").forEach((iframe) => {
if (!iframe.sandbox.contains('allow-top-navigation')) reloadRequired = true;
})
if (reloadRequired) updateAndReloadIframes()
}, 1000);
</script>
''', height=0)
Do not know if this will be useful for you
Note: the last part (after the comment // Some weird bug
) was added only because of a bug in our prod environment. May not be necessary. It was not necessary in dev environment.