dash icon indicating copy to clipboard operation
dash copied to clipboard

[BUG] aio components custom attributes not passed down.

Open stevej2608 opened this issue 3 years ago • 2 comments

Describe your context

dash                      2.3.1
dash-core-components      2.0.0
dash-html-components      2.0.0
dash-labs                 1.0.3
dash-table                5.0.0

Following six line demonstrator works with static layout:

 app.layout = layout()

but fails to initialise when invoked dynamically:

  app.layout = layout

The issue is with the method simple_clone(), in dash.py/L566. The Dash layout clone method fails to pass in the value total_items=100. This is significant problem since the sub-classing the standard Dash components is used extensively when implementing the reusable components AIO pattern.

class MyDiv(html.Div):
    def __init__(self, children=None, className='some-class', total_items=None, page_size=10):

        # Fails with TypeError: unsupported operand type(s) for /: 'NoneType' and 'int'
        pages = total_items / page_size

        print(pages)
        super().__init__(pages, className=className)

def layout():
    return MyDiv(total_items=100)

stevej2608 avatar Mar 31 '22 09:03 stevej2608

With this code, you can extend the component with new props.

class MyDiv(html.Div):
    def __init__(self, children=None, className='some-class', total_items=None, page_size=10):

        # Fails with TypeError: unsupported operand type(s) for /: 'NoneType' and 'int'
        pages = total_items / page_size

        print(pages)
        super().__init__(pages, className=className)

        self._prop_names.extend(["total_items","page_size"])
        self.total_items=total_items
        self.page_size=page_size

nickmelnikov82 avatar Apr 06 '22 12:04 nickmelnikov82

Thanks for bringing this to our attention @stevej2608 - and nice find @nickmelnikov82! I'd consider your solution a hack though, as we don't want users depending on internals like _prop_names that may have other undocumented effects or might break later. A more robust workaround would be to create app.validation_layout

I think the ideal solution here would be to rewrite simple_clone so we don't call the constructor for the class we find. Two options occur to me:

  • Instantiate base components (maybe via some special-purpose class like ComponentClone that we exclude from being registered) that recreates the required internals of html.Div.__init__ (or whatever Dash component) by pulling attrs out of the existing component.
  • Figure out the correct auto-generated Dash component class by traversing the class hierarchy, and instantiate that.

alexcjohnson avatar Apr 06 '22 15:04 alexcjohnson