The currency input widget allows to input a currency value.
agent.customize_collection('product').add_action('Change price', {"scope": "Single","form": [ {"label": "Price","type": "Number","widget": "CurrencyInput","placeholder": "Enter the new price","is_required": True,"min": 0,"max": 1000,"step": 1,"currency": 'USD',"base": 'Unit', }, ],"execute": lambdacontext, result_builder: pass, # perform work here})
The above code will produce the following form:
Options
DatePicker widget
The date picker widget allows to input a date in a form
from datetime import datetime, timedeltaagent.customize_collection('order').add_action('Set shipping date', {"scope": "Single","form": [ {"label": "Shipping date","type": "Date","widget": "DatePicker","format": 'DD-MM-YYYY',"min": datetime.now() -timedelta(days=10),"max": datetime.now(),"placeholder": "please indicate when you shipped the item", }, ],"execute": lambdacontext, result_builder: pass, # perform work here})
The above code will produce the following form :
Note: using a Dateonly field type will hide the time section from the date picker
Options
The dates are sent as ISO 8601 formatted strings over the network. In order to use them as Date object in your hooks, you can parse them directly like so
Dropdown widget
The dropdown widget allows to select a value from a list of options.
In this next example, we call a remote api to get a list of products and then perform a custom filter based on given fields of the json response, and return the first 25. This example uses "search": "dynamic" dropdown widget, which provides you with the search_value in the callback context.
Note: when a search is performed, only the field on which it is performed will have its options recomputed.
from forestadmin.datasource_toolkit.decorators.action.context.base import ( ActionContext)import requestsdefoptions_fn(context: ActionContext,search_value:str|None): products = requests.get('https://api.fake-eshop.com/v2/products').json() searched_products = []for product in products:if search_value isNone:# case of initialization searched_products.append({ "label": product["name"], "value": product["id"] })continuefor field in ['description','name','features','keyword','category']:if search_value.lower()in product[field].lower(): searched_products.append({ "label": product["name"], "value": product["id"] })breakreturnsorted(searched_products, key=lambdax: ["label"])[0:25]agent.customize_collection('product').add_action('Add more products', {"scope": "Global","form": [ {"label": "Select some products","type": "StringList","widget": "Dropdown","options": options_fn,"search": "dynamic", }, ],"execute": lambdacontext, result_builder: pass, # perform work here})
Options
File picker widget
The file picker allows to upload files
import osfrom forestadmin.datasource_toolkit.interfaces.actions import Filefrom forestadmin.datasource_toolkit.decorators.action.context.single import ( ActionContextSingle)from forestadmin.datasource_toolkit.decorators.action.result_builder import ( ResultBuilder)defread_file(path:str):withopen(path, "rb")as fin:return fin.read()defwrite_file(directory:str,file: File):withopen(os.path.join(directory, os.path.basename(file.name)), "wb")as fout: fout.write(file.buffer)asyncdefexecute(context: ActionContextSingle,result_builder: ResultBuilder):try: username =await context.get_record(["username"])["username"] user_directory = os.path.join( __dirname,'data','documents',sanitize(username), )write_file(user_director, context.form_values["Avatar picture"])for f in context.form_values["Identification"]:write_file(user_director, f)return result_builder.success("Profile updated")exceptExceptionas exc:return result_builder.error(f"Upload failed with error: {exc}")agent.customize_collection('user').add_action('Update user identification details', {"scope": "Single","form": [ {"label": "Avatar picture","type": "File","widget": "FilePicker","description": "Upload a profile picture or leave it to use the default one","extensions": ['png', 'jpg'],"max_size_mb": 20,"default_value": readFile( os.path.join(__dirname, './data/avatars/default-avatar.png'), ), }, {"label": "Identification","type": "FileList","widget": "FilePicker","description": "Upload up to 4 documents to identify the user","extensions": ["png", "jpg", "bmp", "pdf", "gif"],"max_size_mb": 2,"max_count": 4,"is_required": True, }, ],"execute": execute})
The above code will produce the following form:
Options
JSON editor widget
The JSON editor widget display a rich editor with syntax highlighting for JSON.
Using the options function, you can dynamically change the list of options based on the context, which contains information about the selected records and other values in the form. More info about dynamic configuration.
Rich text widget
The rich text widget allows to input a formatted text value.
agent.customize_collection('product').add_action('Leave a review', {"scope": "Single","form": [ {"label": "Comment","type": "String","widget": "RichText","is_required": True,"placeholder": "Type your comment here", }, ],"execute": lambdacontext, result_builder: pass, # perform work here})
The above code will produce the following form:
Options
Text area widget
The text area widget allows to input a multiline string value.
agent.customize_collection('product').add_action('Leave a review', {"scope": "Single","form": [ {"label": "Comment","type": "String","widget": "TextArea","is_required": True,"placeholder": "Type your comment here...", }, ],"execute": lambdacontext, result_builder: pass, # perform work here})
The above code will produce the following form:
Options
Text input widget
The text input widget allows to input a string value.
The user dropdown widget allows to input a user or list of users from the project
agent.customize_collection('Ticket').add_action('Assign to the record', {"scope": "Single","form": [ {"label": "Manager","type": "String","widget": "UserDropdown","placeholder": "Select the manager in charge", }, {"label": "Operators","type": "StringList","widget": "UserDropdown","placeholder": "Select operators for this record", }, ],"execute": lambdacontext, result_builder: pass, # perform work here})
The above code will produce the following form (once the user has selected some users)