Skip to main content

actions

ActionInputs

from dara.core.interactivity.actions import ActionInputs

class ActionInputs(BaseModel)

Base class for all action inputs

ActionContext

from dara.core.interactivity.actions import ActionContext

class ActionContext(BaseModel)

Base class for action context

@deprecated: used in deprecated action wrappers

Attributes

  • extras: List[Any]
  • inputs: ActionInputs

ComponentActionContext

from dara.core.interactivity.actions import ComponentActionContext

class ComponentActionContext(ActionContext)

ActionContext for actions that only require component value

Attributes

  • inputs: ComponentActionInputs

UpdateVariableImpl

from dara.core.interactivity.actions import UpdateVariableImpl

class UpdateVariableImpl(ActionImpl)

Update a given variable to provided value. Can be used standalone for updating to static values.

For more complex cases use the @action decorator and the ctx.update method on the injected context.

from dara.core import Variable, UpdateVariableImpl
from dara.components import Button

my_var = Variable(0)

Button(
'UpdateVariable',
onclick=UpdateVariableImpl(my_var, 5),
)

Arguments:

  • variable: the variable to update
  • value: the new value for the variable

Attributes

  • variable: Union[Variable, UrlVariable, DataVariable]
  • value: Any
  • INPUT: ClassVar[str]
  • TOGGLE: ClassVar[str]

INPUT

Special value for value that will be replaced with the input value

TOGGLE

Special value for value that will toggle the variable value

UpdateVariable

from dara.core.interactivity.actions import UpdateVariable

@deprecated('Use @action or `UpdateVariableImpl` for simple cases')
class UpdateVariable(AnnotatedAction)

@deprecated: Passing in resolvers is deprecated, use ctx.update in an @action or UpdateVariableImpl instead. UpdateVariableImpl will be renamed to UpdateVariable in Dara 2.0.

The UpdateVariable action can be passed to any ComponentInstance prop accepting an action and trigger the update of a Variable, UrlVariable or DataVariable. The resolver function takes a Context param which will feed the inputs: old and new as well as any extras passed through.

Below an example of how a resolver might look:

from dara.core import Variable, UpdateVariable
from dara.components import Button

my_var = Variable(0)
x = Variable(1)
y = Variable(2)
z = Variable(3)

def my_resolver(ctx: UpdateVariable.Ctx):
# The UpdateVariable action has two inputs predefined, old, which is the value of
# the variable before update, and new which would have for example the selected value
# of a `Select` component.
old = ctx.inputs.old
new = ctx.inputs.new

# The resolved values of any extras passed are returned as a list
x, y, z = ctx.extras

return old + x + y * z

Button(
'UpdateVariable',
onclick=UpdateVariable(variable=my_var, resolver=my_resolver, extras=[x,y,z]),
)

Example of how you could use UpdateVariable to toggle between true and false:


from dara.core import Variable, UpdateVariable
from dara.components import Button

var = Variable(True)

Button(
'Toggle',
onclick=UpdateVariable(variable=var, resolver=lambda ctx: not ctx.inputs.old),
)

Example of using UpdateVariable to sync values:


from dara.core import Variable, UpdateVariable
from dara.components import Select

var = Variable('first')

Select(
value=Variable('first'),
items=['first', 'second', 'third'],
onchange=UpdateVariable(lambda ctx: ctx.inputs.new, var),
)

Attributes

  • Ctx: ClassVar[type[UpdateVariableContext]]
  • variable: Union[Variable, DataVariable, UrlVariable]
  • extras: Optional[List[AnyVariable]]

Methods

__init__

def __init__(resolver: Callable[[UpdateVariableContext], Any],
variable: Union[Variable, DataVariable, UrlVariable],
extras: Optional[List[AnyVariable]] = None)

Arguments:

  • resolver: a function to resolve the new value for the variable. Takes one arguments: containing a context of type Updatevariable.Ctx
  • variable: the variable or url variable to update with a new value upon triggering the action
  • extras: any extra variables to resolve and pass to the resolution function context

TriggerVariable

from dara.core.interactivity.actions import TriggerVariable

class TriggerVariable(ActionImpl)

Force a recalculation of a DerivedVariable.


from dara.core import action, ConfigurationBuilder, Variable, DerivedVariable, TriggerVariable
from dara.components import Stack, Button, Text

config = ConfigurationBuilder()

var1 = Variable(1)
var2 = Variable(2)
der_var = DerivedVariable(lambda x, y: x + y, variables=[var1, var2], deps=[var2])

@action
async def update(ctx: action.Ctx, previous_value: int):
await ctx.update(var_1, previous_value + 1)

def test_page():
return Stack(
# When clicking this button der_var syncs and calculates latest sum value
Button('Trigger der_var', onclick=TriggerVariable(variable=der_var)),

# Because var1 is not a deps of der_var changing its value does not trigger an update
Button('Add 1 to var1', onclick=update(var_1)),

Stack(Text('der_var: '), Text(der_var), direction='horizontal'),
Stack(Text('var1: '), Text(var1), direction='horizontal'),
Stack(Text('var2: '), Text(var2), direction='horizontal'),
)


config.add_page(name='Trigger Variable', content=test_page())

Attributes

  • variable: DerivedVariable
  • force: bool
from dara.core.interactivity.actions import NavigateToImpl

class NavigateToImpl(ActionImpl)

Navigate to a given url.

Basic example of how to use NavigateToImpl:


from dara.core import NavigateToImpl, Variable, ConfigurationBuilder
from dara.components import Stack, Button, Select

config = ConfigurationBuilder()

def test_page():
return Stack(
# open in the same tab
Button('Go to Another Page', onclick=NavigateToImpl(url='/another-page')),
)


def another_page():
return Stack(
# open in a new tab
Button('Go to Another Page', onclick=NavigateToImpl(url='/test-page', new_tab=True)),
)


config.add_page(name='Test Page', content=test_page())
config.add_page(name='Another Page', content=another_page())

Attributes

  • url: Optional[str]
  • new_tab: bool
@deprecated('Use @action or `NavigateToImpl` for simple cases')
def NavigateTo(url: Union[str, Callable[[Any], str]],
new_tab: bool = False,
extras: Optional[List[AnyVariable]] = None)

@deprecated: Passing in resolvers is deprecated, use ctx.navigate in an @action or NavigateToImpl instead.

The NavigateTo action can be passed to any ComponentInstance prop accepting an ActionInstance and will trigger a change in route based on the url passed. The url can be a static string, or it can be a function that will be called with the element that triggered the action (the structure of this will depend on the component this action is passed to).

Basic example of how to use NavigateTo:


from dara.core import NavigateTo, Variable
from dara.core.configuration import ConfigurationBuilder
from dara.core.css import get_icon
from dara.components import Stack, Button, Select

config = ConfigurationBuilder()


def test_page():
return Stack(
# passing url as a static string
Button('Go to Another Page', onclick=NavigateTo('/another-page')),
)


def another_page():
# passing url as a function based on component value
return Stack(
Select(
value=Variable('/test-page'),
items=['/test-page', '/another-page', 'https://www.google.com/'],
onchange=NavigateTo(lambda ctx: ctx.inputs.value),
)
)


config.add_page(name='Test Page', content=test_page(), icon=get_icon('shield-dog'))
config.add_page(name='Another Page', content=another_page(), icon=get_icon('shield-cat'))

Logout

def Logout()

Logout action, this triggers the UI to logout the user

Example of adding Logout action to a button:


from dara.core import ConfigurationBuilder, Logout
from dara.core.auth import BasicAuthConfig
from dara.components import Stack, Button

config = ConfigurationBuilder()
config.add_auth(BasicAuthConfig(username='test', password='test'))


def test_page():
return Stack(Button('Logout', onclick=Logout()))


config.add_page(name='Logout Page', content=test_page())

ResetVariables

from dara.core.interactivity.actions import ResetVariables

class ResetVariables(ActionImpl)

Reset a number of variables to their default values

Basic example of resetting a Variable:


from dara.core import Variable, ResetVariables, UpdateVariable
from dara.core.configuration import ConfigurationBuilder
from dara.core.css import get_icon
from dara.components import Stack, Button, Text

config = ConfigurationBuilder()

my_var = Variable(0)


def test_page():
return Stack(
Text(my_var),
# when clicked, 1 is added to my_var
Button('Add', onclick=UpdateVariable(lambda ctx: ctx.inputs.old + 1, my_var)),
# when clicked my_var goes back to its initial value: 0
Button('Reset', onclick=ResetVariables(variables=[my_var])),
)


config.add_page(name='ResetVariable', content=test_page(), icon=get_icon('shrimp'))

Arguments:

  • variables: list of variables to reset

Attributes

  • variables: List[AnyVariable]

Notify

from dara.core.interactivity.actions import Notify

class Notify(ActionImpl)

Notify action, this triggers the UI to create a notification which is presented to the user, with a title and message.


from dara.core import Notify, ConfigurationBuilder

from dara.components import Stack, Button

config = ConfigurationBuilder()


def test_page():
return Stack(
Button(
'Notify',
onclick=Notify(
message='This is the notification message', title='Example', status=Notify.Status.SUCCESS
),
)
)


config.add_page(name='Notify Example', content=test_page())

Attributes

  • key: Optional[str]
  • message: str
  • status: NotificationStatus
  • title: str
  • Status: ClassVar[type[NotificationStatus]]
  • Ctx: ClassVar[type[ComponentActionContext]]

Ctx

@deprecated retained for backwards compatibility, to be removed in 2.0

DownloadContentImpl

from dara.core.interactivity.actions import DownloadContentImpl

class DownloadContentImpl(ActionImpl)

Download action, downloads a given file


from dara.core import ConfigurationBuilder, DownloadContentImpl
from dara.components.components import Button, Stack


config = ConfigurationBuilder()

def test_page():
return Stack(
Button(
'Download File', onclick=DownloadContentImpl(path='/path/to/file', cleanup_file=False)
),
)


config.add_page(name='Download Content', content=test_page)

Attributes

  • code: str

DownloadContent

@deprecated('Use @action instead')
def DownloadContent(resolver: Callable[[ComponentActionContext], str],
extras: Optional[List[AnyVariable]] = None,
cleanup_file: bool = False)

@deprecated This action is deprecated, use ctx.download_file in an @action instead.

Download action, downloads a given file


from dara.core import action, ConfigurationBuilder, DataVariable, DownloadContent
from dara.components.components import Button, Stack


# generate data, alternatively you could load it from a file
df = pandas.DataFrame(data={'x': [1, 2, 3], 'y':[4, 5, 6]})
my_var = DataVariable(df)

config = ConfigurationBuilder()

def return_csv(ctx: DownloadContent.Ctx) -> str:
# The file can be created and saved dynamically here, it should then return a string with a path to it
# To get the component value, e.g. a select component would return the selected value
component_value = ctx.inputs.value

# Getting the value of data passed as extras to the action
data = ctx.extras[0]

# save the data to csv
data.to_csv('<PATH_TO_CSV.csv>')
return '<PATH_TO_CSV.csv>'


def test_page():
return Stack(
Button(
'Download File', onclick=DownloadContent(resolver=return_csv, extras=[my_var], cleanup_file=False)
),
)


config.add_page(name='Download Content', content=test_page)

DownloadContent.Ctx

@deprecated retained for backwards compatibility, to be removed in 2.0

DownloadVariable

from dara.core.interactivity.actions import DownloadVariable

class DownloadVariable(ActionImpl)

Download action, downloads the content of a given variable as a file.

Note that as of now variables ran as a task are not supported.


from dara.core import ConfigurationBuilder, DownloadVariable, Variable
from dara.components import Stack, Button

config = ConfigurationBuilder()

my_var = Variable({'foo': 'bar'})

def test_page():
return Stack(
Button(
'Download Variable',
onclick=DownloadVariable(variable=my_var, file_name='test_file', type='json'),
)
)


config.add_page(name='Download Variable', content=test_page())

Attributes

  • variable: AnyVariable
  • file_name: Optional[str]
  • type: Literal[]

SideEffect

@deprecated('Use @action instead')
def SideEffect(function: Callable[[ComponentActionContext], Any],
extras: Optional[List[AnyVariable]] = None,
block: bool = False)

@deprecated: This action is deprecated, use @action instead.

The SideEffect action can be passed to any ComponentInstance prop accepting an ActionInstance in order to trigger an arbitrary python function

Example of how to get values from context in SideEffect function:


from dara.core import Variable, SideEffect
from dara.core.configuration import ConfigurationBuilder
from dara.core.css import get_icon
from dara.components import Stack, Select

config = ConfigurationBuilder()

x = Variable(0)
y = Variable(1)
z = Variable(2)


def side_effect(ctx: SideEffect.Ctx):
value = ctx.inputs.value
x, y, z = ctx.extras

print('value:', value)
print(f'x:{x}, y:{y}, z:{z}')


def test_page():
return Stack(Select(value=Variable(3), items=[3, 4, 5], onchange=SideEffect(side_effect, extras=[x, y, z])))


config.add_page(name='SideEffect', content=test_page(), icon=get_icon('kiwi-bird'))

SideEffect.Ctx

@deprecated retained for backwards compatibility, to be removed in 2.0

ActionCtx

from dara.core.interactivity.actions import ActionCtx

class ActionCtx()

Action execution context passed to an @action-annotated action when it is being executed.

Exposes input, the input value passed to the action by the invoking components, and an collection of methods for interacting with the frontend.

Attributes

  • _action_send_stream: MemoryObjectSendStream[ActionImpl]
  • _action_receive_stream: MemoryObjectReceiveStream[ActionImpl]
  • _on_action: Callable[[Optional[ActionImpl]], Awaitable]
  • input: Any

Methods

update

async def update(variable: Union[Variable, UrlVariable, DataVariable],
value: Any)

Update a given variable to provided value.

from dara.core import action, Variable
from dara.components import Button

my_var = Variable(0)
x = Variable(1)
y = Variable(2)
z = Variable(3)

**Arguments**:

- `variable`: the variable to update
:param value: the new value for the variable

#### trigger

```python
async def trigger(variable: DerivedVariable, force: bool = True)

Trigger a given DerivedVariable to recalculate.


from dara.core import action, ConfigurationBuilder, Variable, DerivedVariable
from dara.core.configuration import ConfigurationBuilder
from dara.components import Stack, Button, Text

config = ConfigurationBuilder()

var1 = Variable(1)
var2 = Variable(2)
der_var = DerivedVariable(lambda x, y: x + y, variables=[var1, var2], deps=[var2])

@action
async def update(ctx: action.Ctx, previous_value: int):
await ctx.update(var_1, previous_value + 1)

@action
async def trigger(ctx: action.Ctx):
await ctx.trigger(der_var)

def test_page():
return Stack(
# When clicking this button der_var syncs and calculates latest sum value
Button('Trigger der_var', onclick=trigger()),

# Because var1 is not a deps of der_var changing its value does not trigger an update
Button('Add 1 to var1', onclick=update(var_1)),

Stack(Text('der_var: '), Text(der_var), direction='horizontal'),
Stack(Text('var1: '), Text(var1), direction='horizontal'),
Stack(Text('var2: '), Text(var2), direction='horizontal'),
)


config.add_page(name='Trigger Variable', content=test_page())

Arguments:

  • variable: the variable to trigger
  • force: whether to force the recalculation, defaults to True
async def navigate(url: str, new_tab: bool = False)

Navigate to a given url


from dara.core import action, ConfigurationBuilder, Variable
from dara.components import Stack, Button, Select

config = ConfigurationBuilder()

@action
async def navigate_to(ctx: action.Ctx, url: str):
# Navigate to the url provided
await ctx.navigate(url)


def test_page():
return Stack(
Button('Go to Another Page', onclick=navigate_to('/another-page')),
)

@action
async def navigate_to_input(ctx: action.Ctx):
# Navigate to the value of the input provided to the action
await ctx.navigate(ctx.input)

def another_page():
return Stack(
Select(
value=Variable('/test-page'),
items=['/test-page', '/another-page', 'https://www.google.com/'],
onchange=navigate_to_input(),
)
)


config.add_page(name='Test Page', content=test_page())
config.add_page(name='Another Page', content=another_page())

Arguments:

  • url: the url to navigate to
  • new_tab: whether to open the url in a new tab, defaults to False

logout

async def logout()

Logout the current user.


from dara.core import ConfigurationBuilder, action
from dara.core.auth import BasicAuthConfig
from dara.components import Stack, Button

config = ConfigurationBuilder()
config.add_auth(BasicAuthConfig(username='test', password='test'))

@action
async def logout(ctx: action.Ctx):
await ctx.logout()

def test_page():
return Stack(Button('Logout', onclick=logout()))


config.add_page(name='Logout Page', content=test_page())

notify

async def notify(message: str,
title: str,
status: Union[NotificationStatus, NotificationStatusString],
key: Optional[str] = None)

Display a notification toast on the frontend


from dara.core import action, ConfigurationBuilder
from dara.components import Stack, Button

config = ConfigurationBuilder()

@action
async def notify(ctx: action.Ctx):
await ctx.notify(
message='This is the notification message', title='Example', status='SUCCESS'
)

def test_page():
return Stack(
Button(
'Notify',
onclick=notify()
)
)


config.add_page(name='Notify Example', content=test_page())

Arguments:

  • message: the message to display
  • title: the title of the notification
  • status: the status of the notification
  • key: optional key for the notification

reset_variables

async def reset_variables(variables: Union[List[AnyVariable], AnyVariable])

Reset a list of variables to their default values.


from dara.core import Variable, action, ConfigurationBuilder
from dara.components import Stack, Button, Text

config = ConfigurationBuilder()

my_var = Variable(0)

**Arguments**:

- `variables`: a variable or list of variables to reset

#### download\_file

```python
async def download_file(path: str, cleanup: bool = False)

Download a given file.


from dara.core import action, ConfigurationBuilder, DataVariable
from dara.components.components import Button, Stack

# generate data, alternatively you could load it from a file
df = pandas.DataFrame(data={'x': [1, 2, 3], 'y':[4, 5, 6]})
my_var = DataVariable(df)

config = ConfigurationBuilder()

@action
async def download_csv(ctx: action.Ctx, my_var_value: DataFrame) -> str:
# Getting the value of data passed as extras to the action
data = my_var_value

# save the data to csv
data.to_csv('<PATH_TO_CSV.csv>')

# Instruct the frontend to download the file and clean up afterwards
await ctx.download_file(path='<PATH_TO_CSV.csv>', cleanup=True)


def test_page():
return Stack(
Button(
'Download File', onclick=download_csv(my_var)
),
)


config.add_page(name='Download Content', content=test_page)

Arguments:

  • path: the path to the file to download
  • cleanup: whether to delete the file after download

download_variable

async def download_variable(variable: AnyVariable,
file_name: Optional[str] = None,
type: Literal['csv', 'xlsx', 'json'] = 'csv')

Download the content of a given variable as a file.

Note that the content of the file must be valid for the given type.


from dara.core import action, ConfigurationBuilder, Variable
from dara.components import Stack, Button

config = ConfigurationBuilder()

my_var = Variable({'foo': 'bar'})

@action
async def download(ctx: action.Ctx):
await ctx.download_variable(variable=my_var, file_name='test_file', type='json')

def test_page():
return Stack(
Button(
'Download Variable',
onclick=download(),
)
)


config.add_page(name='Download Variable', content=test_page())

Arguments:

  • variable: the variable to download
  • file_name: optional name of the file to download
  • type: the type of the file to download, defaults to csv

run_task

async def run_task(
func: Callable,
args: Union[List[Any], None] = None,
kwargs: Union[Dict[str, Any], None] = None,
on_progress: Optional[Callable[[TaskProgressUpdate],
Union[None, Awaitable[None]]]] = None)

Run a calculation as a task in a separate process. Recommended for CPU intensive tasks.

Returns the result of the task function.

Note that the function must be defined in a separate module as configured in task_module field of the configuration builder. This is because Dara spawns separate worker processes only designed to run functions from that designated module.

from dara.core import ConfigurationBuilder, TaskProgressUpdate, action, ActionCtx, Variable
from dara.components import Text, Stack, Button
from .my_module import my_task_function

config = ConfigurationBuilder()
config.task_module = 'my_module'

status = Variable('Not started')

@action
async def my_task(ctx: ActionCtx):
async def on_progress(update: TaskProgressUpdate):
await ctx.update(status, f'Progress: {update.progress}% - {update.message}')

try:
result = await ctx.run_task(my_task_function, args=[1, 10], on_progress=on_progress)
await ctx.update(status, f'Result: {result}')
except Exception as e:
await ctx.update(status, f'Error: {e}')

def task_page():
return Stack(Text('Status display:'), Text(text=status), Button('Run', onclick=my_task()))

config.add_page(name='task', content=task_page())

Arguments:

  • func: the function to run as a task
  • args: the arguments to pass to the function
  • kwargs: the keyword arguments to pass to the function
  • on_progress: a callback to receive progress updates

execute_action

async def execute_action(action: ActionImpl)

Execute a given action.

Arguments:

  • action: the action impl instance to execute

ACTION_CONTEXT

Current execution context

assert_no_context

def assert_no_context(alternative: str)

Assert that no action context is active.

This is used to ensure shortcut actions are not used within an @action as they are synchronous and return a simple object, while to execute it once needs to await its execution.

action

from dara.core.interactivity.actions import action

class action()

A decorator for creating actions. Actions are used to trigger changes in the UI, such as updating a variable, navigating to a new page, etc.

The decorator injects an ActionCtx object as the first argument to the decorated function, which can be used to access the available actions as well as the input value of the component that triggered the action. Note that the context methods are asynchronous, so the decorated function must be async to use them.

An @action-decorated function can be called with a list of Variable and non-Variable arguments. The non-Variable arguments will be passed as-is to the decorated function, while the Variable arguments will be passed as the current value of the Variable.

from dara.core import action, Variable
from dara.components import Select, Item

some_variable = Variable(1)
other_variable = Variable(2)

@action
async def my_action(ctx: action.Ctx, arg_1: int, arg_2: int):
# Value coming from the component, in this case the selected item
value = ctx.input
# Your action logic...

# Update `some_variable` to `value` multiplied by arg_1 and arg_2
await ctx.update(variable=some_variable, value=value * arg_1 * arg_2)


Select(
items=[Item(label='item1', value=1), Item(label='item2', value=2)],
onchange=my_action(2, other_variable)
)

Attributes

  • Ctx: ClassVar[type[ActionCtx]]

Methods

__get__

def __get__(instance: Any, owner=None) -> Callable[..., Any]

Get descriptor for the decorated function.

Necessary to support instance/class bound methods.