Skip to content

Local JS-dependency not available on mount for custom component (d3.js) #4243

Open
@ursa-minor-13

Description

Description

I'm working with d3.js-based visualizations ([email protected] -- https://cdn.jsdelivr.net/npm/d3@7) inside a custom component ([email protected]).
When refactoring my component to the new unified 3rd-party dependency declaration (#2991), the locally served library gets imported, but there seems to be an issue during the import:

When the component is initialized, an error is thrown: d3.select is not a function (for code example, see below).
Running the same d3.js-based command afterwards from the console produces the correct result (as indicated by the image below).

I'm currently unsure whether this is a nicegui- or js-import-related problem.
However, based on the fact that the module is available later, I'd assume that there is some timing problem related to nicegui.

Image


Minimal example (using dependencies -- throws error)

Python-component:

from nicegui import ui, app
from nicegui.element import Element as NiceGuiBaseElement

class VizContainer(NiceGuiBaseElement, component='VizContainer.js', dependencies=['./d3.js']):
    
    def __init__(self, tag = None, *, _client = None):
        super().__init__(tag, _client=_client)
        self._props = {'svg_width': 500,'svg_height': 500,}

myViz = VizContainer()

app.native.start_args['debug'] = True
ui.run(native=True)

JS-component:

import * as d3 from 'd3';

export default {
    name: 'VisualComponent',
    template: `
      <div id="svg-body">
        <svg id="svg" :width="$props.svg_width" :height="$props.svg_height"></svg>
      </div>
      `,
    mounted() {
        this.initSVG()
    },
    props: [
        'svg_width',
        'svg_height'
    ],
    methods: {
        initSVG() {
            d3.select('#svg').append('circle').attr('r', '200px').style('fill','red')
        }
    },
}

Minimal example (using deprecated libraries -- runs as intended)

Python-component:

from nicegui import ui, app
from nicegui.element import Element as NiceGuiBaseElement

class VizContainer(NiceGuiBaseElement, component='VizContainer.js', libraries=['./d3.js']):
    
    def __init__(self, tag = None, *, _client = None):
        super().__init__(tag, _client=_client)
        self._props = {'svg_width': 500,'svg_height': 500,}

myViz = VizContainer()

app.native.start_args['debug'] = True
ui.run(native=True)

JS-component:

export default {
    name: 'VisualComponent',
    template: `
      <div id="svg-body">
        <svg id="svg" :width="$props.svg_width" :height="$props.svg_height"></svg>
      </div>
      `,
    mounted() {
        this.initSVG()
    },
    props: [
        'svg_width',
        'svg_height'
    ],
    methods: {
        initSVG() {
            d3.select('#svg').append('circle').attr('r', '200px').style('fill','red')
        }
    },
}

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions