Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENG-4001] Doc bash fixes for UI section #1056

Merged
merged 12 commits into from
Nov 28, 2024
6 changes: 3 additions & 3 deletions docs/assets/referencing_assets.md → docs/assets/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import reflex as rx

# Assets

Static files such as images and stylesheets can be placed in `"assets/"` folder of the project. These files can be referenced within your app.
Static files such as images and stylesheets can be placed in `assets/` folder of the project. These files can be referenced within your app.

```md alert
# Assets are copied during the build process.
Expand All @@ -15,7 +15,7 @@ when running in production mode. The `assets/` folder should only be used for st

## Referencing Assets

To reference an image in the `"assets/"` simply pass the relative path as a prop.
To reference an image in the `assets/` simply pass the relative path as a prop.

For example, you can store your logo in your assets folder:

Expand All @@ -38,4 +38,4 @@ rx.image(src="/Reflex.svg", width="5em")

The favicon is the small icon that appears in the browser tab.

You can add a `"favicon.ico"` file to the `"assets/"` folder to change the favicon.
You can add a `favicon.ico` file to the `assets/` folder to change the favicon.
26 changes: 0 additions & 26 deletions docs/components/conditional_props.md
Original file line number Diff line number Diff line change
@@ -1,26 +0,0 @@
```python exec
import reflex as rx
```

# Conditional Props

Sometimes you want to set a prop based on a condition. You can use the `rx.cond` function to do this.

```python demo exec
class PropCondState(rx.State):

value: int

@rx.event
def set_end(self, value: list[int]):
self.value = value[0]


def cond_prop():
return rx.slider(
default_value=[50],
on_value_commit=PropCondState.set_end,
color_scheme=rx.cond(PropCondState.value > 50, "green", "pink"),
width="100%",
)
```
250 changes: 21 additions & 229 deletions docs/components/conditional_rendering.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
```python exec
import reflex as rx

from pcweb.pages.docs import vars, library
from pcweb.pages.docs import library
from pcweb.pages import docs
```

# Conditional Rendering

We use the `cond` component to conditionally render components. The `cond` component acts in a similar way to a conditional (ternary) operator in python, acting in a similar fashion to an `if-else` statement.
Recall from the [basics]({docs.getting_started.basics.path}) that we cannot use Python `if/else` statements when referencing state vars in Reflex. Instead, use the `rx.cond` component to conditionally render components or set props based on the value of a state var.

```md video https://youtube.com/embed/ITOZkzjtjUA?start=6040&end=6463
# Video: Conditional Rendering
Expand All @@ -20,13 +21,7 @@ We use the `cond` component to conditionally render components. The `cond` compo
rx.box(height="2em")
```

Here is a simple example to show how by checking the value of the state var `show` we can render either `blue` text or `red` text.

The first argument to the `cond` component is the condition we are checking. Here the condition is the value of the state var boolean `show`.

If `show` is `True` then the 2nd argument to the `cond` component is rendered, in this case that is `rx.text("Text 1", color="blue")`.

If `show` is `False` then the 3rd argument to the `cond` component is rendered, in this case that is `rx.text("Text 2", color="red")`.
Below is a simple example showing how to toggle between two text components by checking the value of the state var `show`.

```python demo exec
class CondSimpleState(rx.State):
Expand All @@ -48,243 +43,40 @@ def cond_simple_example():
)
```

## Var Operations (negation)

You can use var operations with the `cond` component. To learn more generally about var operators check out [these docs]({vars.var_operations.path}). The logical operator `~` can be used to negate a condition. In this example we show that by negating the condition `~CondNegativeState.show` within the cond, we then render the `rx.text("Text 1", color="blue")` component when the state var `show` is negative.

```python demo exec
class CondNegativeState(rx.State):
show: bool = True

@rx.event
def change(self):
self.show = not (self.show)


def cond_negative_example():
return rx.vstack(
rx.text(f"Value of state var show: {CondNegativeState.show}"),
rx.button("Toggle", on_click=CondNegativeState.change),
rx.cond(
CondNegativeState.show,
rx.text("Text 1", color="blue"),
rx.text("Text 2", color="red"),
),
rx.cond(
~CondNegativeState.show,
rx.text("Text 1", color="blue"),
rx.text("Text 2", color="red"),
),
)
```

## Multiple Conditions

It is also possible to make up complex conditions using the `logical or` (|) and `logical and` (&) operators.

Here we have an example using the var operators `>=`, `<=`, `&`. We define a condition that if a person has an age between 18 and 65, including those ages, they are able to work, otherwise they cannot.

We could equally use the operator `|` to represent a `logical or` in one of our conditions.

```python demo exec
import random

class CondComplexState(rx.State):
age: int = 19

@rx.event
def change(self):
self.age = random.randint(0, 100)


def cond_complex_example():
return rx.vstack(
rx.button("Toggle", on_click=CondComplexState.change),
rx.text(f"Age: {CondComplexState.age}"),
rx.cond(
(CondComplexState.age >= 18) & (CondComplexState.age <=65),
rx.text("You can work!", color="green"),
rx.text("You cannot work!", color="red"),
),
)

```

## Reusing Cond

We can also reuse a `cond` component several times by defining it within a function that returns a `cond`.

In this example we define the function `render_item`. This function takes in an `item`, uses the `cond` to check if the item `is_packed`. If it is packed it returns the `item_name` with a `✔` next to it, and if not then it just returns the `item_name`.

```python demo exec
import dataclasses

@dataclasses.dataclass
class ToDoListItem:
item_name: str
is_packed: bool

class CondRepeatState(rx.State):
to_do_list: list[ToDoListItem] = [
ToDoListItem(item_name="Space suit", is_packed=True),
ToDoListItem(item_name="Helmet", is_packed=True),
ToDoListItem(item_name="Back Pack", is_packed=False),
]


def render_item(item: [str, bool]):
return rx.cond(
item.is_packed,
rx.list_item(item.item_name + ' ✔'),
rx.list_item(item.item_name),
)

def packing_list():
return rx.vstack(
rx.text("Sammy's Packing List"),
rx.list(rx.foreach(CondRepeatState.to_do_list, render_item)),
)

```

## Nested Conditional

We can also nest `cond` components within each other to create more complex logic. In python we can have an `if` statement that then has several `elif` statements before finishing with an `else`. This is also possible in reflex using nested `cond` components. In this example we check whether a number is positive, negative or zero.

Here is the python logic using `if` statements:

```python
number = 0

if number > 0:
print("Positive number")

elif number == 0:
print('Zero')
else:
print('Negative number')
```

This reflex code that is logically identical:

```python demo exec
import random


class NestedState(rx.State):

num: int = 0

@rx.event
def change(self):
self.num = random.randint(-10, 10)


def cond_nested_example():
return rx.vstack(
rx.button("Toggle", on_click=NestedState.change),
rx.cond(
NestedState.num > 0,
rx.text(f"{NestedState.num} is Positive!", color="orange"),
rx.cond(
NestedState.num == 0,
rx.text(f"{NestedState.num} is Zero!", color="blue"),
rx.text(f"{NestedState.num} is Negative!", color="red"),
)
),
)

```

Here is a more advanced example where we have three numbers and we are checking which of the three is the largest. If any two of them are equal then we return that `Some of the numbers are equal!`.
If `show` is `True` then the first component is rendered (in this case the blue text). Otherwise the second component is rendered (in this case the red text).

The reflex code that follows is logically identical to doing the following in python:
## Conditional Props

```python
a = 8
b = 10
c = 2

if((a>b and a>c) and (a != b and a != c)):
print(a, " is the largest!")
elif((b>a and b>c) and (b != a and b != c)):
print(b, " is the largest!")
elif((c>a and c>b) and (c != a and c != b)):
print(c, " is the largest!")
else:
print("Some of the numbers are equal!")
```
You can also set props conditionally using `rx.cond`. In this example, we set the `color` prop of a text component based on the value of the state var `show`.

```python demo exec
import random


class CNS(rx.State):
# CNS: CondNestedState
a: int = 8
b: int = 10
c: int = 2

class PropCondState(rx.State):

value: int

@rx.event
def change(self):
self.a = random.randint(0, 10)
self.b = random.randint(0, 10)
self.c = random.randint(0, 10)
def set_end(self, value: list[int]):
self.value = value[0]


def cond_nested_example_2():
return rx.vstack(
rx.button("Toggle", on_click=CNS.change),
rx.text(f"a: {CNS.a}, b: {CNS.b}, c: {CNS.c}"),
rx.cond(
((CNS.a > CNS.b) & (CNS.a > CNS.c)) & ((CNS.a != CNS.b) & (CNS.a != CNS.c)),
rx.text(f"{CNS.a} is the largest!", color="green"),
rx.cond(
((CNS.b > CNS.a) & (CNS.b > CNS.c)) & ((CNS.b != CNS.a) & (CNS.b != CNS.c)),
rx.text(f"{CNS.b} is the largest!", color="orange"),
rx.cond(
((CNS.c > CNS.a) & (CNS.c > CNS.b)) & ((CNS.c != CNS.a) & (CNS.c != CNS.b)),
rx.text(f"{CNS.c} is the largest!", color="blue"),
rx.text("Some of the numbers are equal!", color="red"),
),
),
),
def cond_prop():
return rx.slider(
default_value=[50],
on_value_commit=PropCondState.set_end,
color_scheme=rx.cond(PropCondState.value > 50, "green", "pink"),
width="100%",
)

```

## Cond used as a style prop

`Cond` can also be used to show and hide content in your reflex app. In this example, we have no third argument to the `cond` operator which means that nothing is rendered if the condition is false.

```python demo exec
class CondStyleState(rx.State):
show: bool = False
img_url: str = "/preview.png"

@rx.event
def change(self):
self.show = not (self.show)
## Var Operations

You can use [var operations]({docs.vars.var_operations.path}) with the `cond` component for more complex conditions. See the full [cond reference]({library.dynamic_rendering.cond.path}) for more details.

def cond_style_example():
return rx.vstack(
rx.button("Toggle", on_click=CondStyleState.change),
rx.cond(
CondStyleState.show,
rx.image(
src=CondStyleState.img_url,
height="25em",
width="25em",
),
),
)
```

## Multiple Conditional Statements

The `rx.match` component in Reflex provides a powerful alternative to`rx.cond` for handling multiple conditional statements and structural pattern matching. This component allows you to handle multiple conditions and their associated components in a cleaner and more readable way compared to nested `rx.cond` structures.
The [`rx.match`]({library.dynamic_rendering.match.path}) component in Reflex provides a powerful alternative to`rx.cond` for handling multiple conditional statements and structural pattern matching. This component allows you to handle multiple conditions and their associated components in a cleaner and more readable way compared to nested `rx.cond` structures.

```python demo exec
from typing import List
Expand Down
Loading