Iframe using dynamically html file from blob or local

Hi,

I have created an app where the user fetch data from a blob storage.

On the blob storage there is an index.html file which I would like to embed in the app. It is an interactive visualisation from a Ansys solver. Beside the index.html file there are some required folders that needs to be used.

If I copy the folders and the index.html to the assets folder, then it is straightforward to make an Iframe which works as wanted. But if the user select another result then I need to update the index.html file.

First go was to simple just make a callback that download the new index file into the assets folder. This doesnt work, because everytime I copy to the assets folder the dash app reloads and the user would then again have to select the data.

Of course the best solution would be just to use blob storage directly instead of copy, I have read about it here javascript - set a Blob as the “src” of an iframe - Stack Overflow but dont know how to implement that in a Dash app.

The second solution is what I have been trying i.e. copy the index.html file to the assets folder. Maybe I can copy to another folder and then do something clever?

Any help much appreciated

edit:

I look a little more in the details what it is I am trying to do. In the index.html file the only thing I am changing is the variable shown below (proxy_img = VARIABLE. Maybe I dont need an Iframe at all? Can I just create an object which is rendered if there is a variable?

<!DOCTYPE html>
<html data-color-mode="light" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Report - ADR</title>

    <script src="./ansys/nexus/utils/js-unzip.js"></script>
    <script src="./ansys/nexus/utils/js-inflate.js"></script>
    <script src="./ansys/nexus/ANSYSViewer_min.js"></script> 
    <script src="./ansys/nexus/viewer-loader.js"></script>

</head>

<div class="col justify-content-center"><div class="col-md-auto"><div class='avz-viewer' id='avz_viewer_319ffe596954461e910340b21d034b45' style='display:inline-block;top:0px;left:0px;width:960px;height:720px;margin:0;border:0;padding:0;fixed:absolute;background:white;'>

<ansys-nexus-viewer src_ext="AVZ" proxy_img= VARIABLE
</div>
</div></div>

</html>

edit2
So the java function I need to get is located in viewer-load.js called AnsysNexusViewer so I need to parse the string into this function. Is this is were Clientside Callbacks | Dash for Python Documentation | Plotly has to be used?

Next step:

from dash import Dash, dcc, html, Input, Output, callback, clientside_callback
import pandas as pd


def read_first_line(filename):  
    with open(filename, 'r') as f:  
        first_line = f.readline()  
    return first_line  
filename = 'pictest.txt'  
first_line = read_first_line(filename)  
  

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = Dash(__name__, external_stylesheets=external_stylesheets)


app.layout = html.Div([
    html.Div(id='test'),
    html.Button('Button', id='button'),

])


clientside_callback(
    """
    function() {
        return AnsysNexusViewer(src_ext="AVZ",proxy_img=first_line);
    }
    """,
    Output('test', 'children'),
    Input('button', 'n_clicks')
)

if __name__ == '__main__':
    app.run(debug=True)

from the viewer_load.js I have this Class:

class AnsysNexusViewer extends HTMLElement {

    // Called at object creation
    constructor() {
        super();
        this._guid = this.generateUID();
        this._renderer = "webgl";  // 'webgl' or 'envnc'
        this._renderer_options = null;  // pass-thru to the renderer
        this._src = null;  // 3D data source URL
        this._src_ext = null; // 3D data source extension (type) used with data URI src values
        this._proxy_img = null;  // proxy image URL
        this._proxy_size = [0, 0]; // The size of the proxy image
        this._observer = null; // resizing observer
        this._perspective = false;  // perspective mode
        this._aspect_ratio = null;  // aspect_ratio override
        this._render_instance = null; // The specific instance for the target renderer
        this._proxy_only = null;  // if not null, proxy hover message. No activation possible.
        this._ui = "";            // 'envnc' renderer uses this to selected a UI.  'none' or 'simple'
    }

The files are located in the assets folder. So I assume Dash knows about the different java scripts.

So I would assume that I need to activate this class which return a html element. I am ativated the clientside callback by pressing the button. The function does not take any inputs. But the function inside does. But it doesnt really works, get this error

TypeError: Cannot read properties of undefined (reading ‘children’)

at _callee3$ (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:577:58)

at tryCatch (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:411:2404)

at Generator._invoke (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:411:1964)

at Generator.next (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:411:3255)

at asyncGeneratorStep (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:415:103)

at _next (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:416:194)

at http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:416:364

at new Promise (<anonymous>)

at http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:416:97

at handleClientside (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:529:28)

So am I getting closer or further away from a solution?

It was probably the wrong direction I took.

In the app below I read a txt file add it to dcc.Store component.

When I press the button I use clientsideCallback to activate the javascript.

But I get the following error


(This error originated from the built-in JavaScript code that runs Dash apps. Click to see the full stack trace or open your browser's console.)
TypeError: Class constructor AnsysNexusViewer cannot be invoked without 'new'

    at ns.children (http://127.0.0.1:8050/:49:95)

    at _callee3$ (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:577:74)

    at tryCatch (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:411:2404)

    at Generator._invoke (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:411:1964)

    at Generator.next (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:411:3255)

    at asyncGeneratorStep (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:415:103)

    at _next (http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:416:194)

    at http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:416:364

    at new Promise (<anonymous>)

    at http://127.0.0.1:8050/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_9_0m1685019644.dev.js:416:97
from dash import html, Output, Input, Dash, no_update, dcc, State

def read_first_line(filename):  
    with open(filename, 'r') as f:  
        first_line = f.readline()  
    return first_line  
filename = 'pictest.txt'

first_line = read_first_line(filename) 


app = Dash(__name__)
app.layout = html.Div(
    [
        html.Button('testing', 'testing'),
        html.Div(id='test'),
        dcc.Store(id='memory', data = first_line)
        
    ]
)

app.clientside_callback(
    """
    function (n, data) {
        if (n) {
            return {'type': 'Div', 'namespace': 'dash_html_components', 'props': {'children': AnsysNexusViewer(src_ext="AVZ",proxy_img=data)}}
        }
        return window.dash_clientside.no_update
    }
    """,
    Output("test", "children"), Input("testing", "n_clicks"), State("memory", "data")
)



if __name__ == "__main__":
    app.run_server(debug=True)