reflex-dev / reflex

🕸️ Web apps in pure Python 🐍
https://reflex.dev
Apache License 2.0
19.79k stars 1.14k forks source link

rx.cond in style #2979

Open a0s opened 6 months ago

a0s commented 6 months ago

Describe the bug I'm not entirely sure if this is a bug or if I'm doing something it's not designed for.

I need style with condition. When i try to do smth like this:

rx.image(
    src="/logoipsum-263.svg",
    style=rx.cond(
        TopBarState.is_debug,
        Style({"border": "1px solid red"}),
        Style({}),
    )
)

or even simple

rx.image(
    src="/logoipsum-263.svg",
    style=rx.cond(
        TopBarState.is_debug,
        {"border": "1px solid red"},
        {},
    )
)

i am getting:

[skipped] site-packages/reflex/components/component.py", line 352, in __init__

TypeError: 'BaseVar' object is not a mapping

[skipped]

TypeError: You may be trying to use an invalid Python function on a state var. When referencing a var inside your render code, only limited var operations are supported. See the var operation docs here

The error contains no useful information, except that rx.cond does not seem to be able to work with the Style() type?

Version: reflex==0.4.6

PasqualePuzio commented 6 months ago

I think the best way to do that is to use rx.cond for keywors arguments. At least that's how we do it and it works perfectly.

For instance:

rx.image(
    src='...',
    width=rx.cond(MyState.my_var,width1,width2),
)
a0s commented 6 months ago

No, it doesn't work for style=

class TopBarState(rx.State):
    is_debug: bool
    debug_enabled: dict[str, str] = {
        "border": "1px solid red"
    }
    debug_disabled: dict[str, str] = {}

rx.image(
  src="/logoipsum-263.svg",
  height="3rem",
  style=rx.cond(
      TopBarState.is_debug,
      TopBarState.debug_enabled,
      TopBarState.debug_disabled,
  ),

got me the same error TypeError: 'BaseVar' object is not a mapping

PasqualePuzio commented 6 months ago

Yeah, what I meant is that instead of passing a style dict you could use rx.cond for every single property. That will probably fix your bug.

Lendemor commented 6 months ago
class DebugState(rx.State):
    enabled: bool

    def toggle(self, _):
        self.enabled = not self.enabled

@rx.page()
def index():
    return rx.vstack(
        rx.switch(on_change=DebugState.toggle),
        rx.image(
            src="favicon.ico",
            style={
                "border": rx.cond(DebugState.enabled, "1px solid red", ""),
            },
        ),
    )
a0s commented 6 months ago

@Lendemor yeah, thank you, this is the only way i found. Ofc, it would be better if rx.cond supports Style() class as one of set of native operands..