Repository navigation
Dars Framework v1.6.8
Release Notes v1.6.8
Component-Level State Updates with updateVRef()
Installation
pip install --upgrade dars-frameworkWhat's New
updateVRef() - Pythonic Component-Level State
Dars Framework v1.6.8 introduces updateVRef(), a powerful new function for updating DOM values and component state without requiring State objects. This completes the component-level state management cycle alongside V().
The Complete Cycle:
- Read:
V("#input")- Extract values (v1.5.8) - Validate:
V("#input").length() >= 3- Boolean validation (v1.6.7) - Update:
updateVRef("#input", "new value")- Update values (v1.6.8) NEW!
Before (v1.6.7) - Raw JavaScript
Button(
"Increment",
on_click=dScript("""
const el = document.querySelector('#count');
const current = parseInt(el.textContent);
el.textContent = current + 1;
""")
)After (v1.6.8) - Declarative Python
Button(
"Increment",
on_click=updateVRef("#count", V("#count").int() + 1)
)Benefits:
- 95% less code
- Type-safe with V() expressions
- Pythonic - no inline JavaScript
- Composable - works with all V() features
- Batch updates - update multiple elements at once
Key Features
1. Simple Value Updates
Update any DOM element value with a single function call:
# Update text content
Button("Set Name", on_click=updateVRef("#name", "John Doe"))
# Update input value
Button("Clear", on_click=updateVRef("#email", ""))
# Update checkbox
Button("Check", on_click=updateVRef("#agree", True))
# Update number
Button("Set Price", on_click=updateVRef("#price", 99.99))2. V() Expression Integration
Use V() expressions to create dynamic updates:
# Copy values
Button("Copy", on_click=updateVRef("#target", V("#source")))
# With transformations
Button("Uppercase", on_click=updateVRef("#output", V("#input").upper()))
# With calculations
Button("Calculate", on_click=updateVRef("#total",
V("#price").float() * V("#qty").int()
))3. Boolean Expression Support
Combine with boolean operators for conditional updates:
# Conditional text
Button("Check Age", on_click=updateVRef("#status",
(V("#age").int() >= 18).then("Adult", "Minor")
))
# Validation messages
Button("Validate", on_click=updateVRef("#message",
(V("#email").includes("@")).then("✓ Valid", "✗ Invalid")
))4. Batch Updates
Update multiple elements with a single call:
# Clear form
Button("Clear All", on_click=updateVRef({
"#name": "",
"#email": "",
"#age": ""
}))
# Fill sample data
Button("Fill Sample", on_click=updateVRef({
"#name": "John Doe",
"#email": "john@example.com",
"#age": 25
}))Complete Examples
Example 1: Counter (No State Object!)
from dars.all import *
@route("/counter")
def counter():
return Page(
Container(
# Display count
Text("0", id="count", style="text-[48px] font-bold"),
# Update buttons
Button("+", on_click=updateVRef("#count", V("#count").int() + 1)),
Button("-", on_click=updateVRef("#count", V("#count").int() - 1)),
Button("Reset", on_click=updateVRef("#count", 0))
)
)Example 2: Form Auto-Fill
@route("/form")
def form():
return Page(
Container(
Input(id="first-name", placeholder="First Name"),
Input(id="last-name", placeholder="Last Name"),
Input(id="full-name", placeholder="Full Name", readonly=True),
# Auto-generate full name
Button(
"Generate Full Name",
on_click=updateVRef("#full-name",
V("#first-name") + " " + V("#last-name")
)
),
# Clear all
Button(
"Clear All",
on_click=updateVRef({
"#first-name": "",
"#last-name": "",
"#full-name": ""
})
)
)
)Example 3: Shopping Cart Calculations
@route("/cart")
def cart():
return Page(
Container(
Input(id="price", input_type="number", value="19.99"),
Input(id="quantity", input_type="number", value="1"),
Text("0", id="total"),
# Calculate total
Button(
"Calculate Total",
on_click=updateVRef("#total",
V("#price").float() * V("#quantity").int()
)
),
# Apply discount
Button(
"Apply 10% Discount",
on_click=updateVRef("#total",
V("#total").float() * 0.9
)
)
)
)Example 4: Smart Validation
@route("/signup")
def signup():
return Page(
Container(
Input(id="username", placeholder="Username"),
Text("", id="username-status"),
# Validate and normalize
Button(
"Validate Username",
on_click=updateVRef("#username-status",
(V("#username").length() >= 3).then(
"✓ Valid username",
"✗ Too short (need 3+ characters)"
)
)
),
# Auto-fix: lowercase
Button(
"Normalize",
on_click=updateVRef("#username",
V("#username").lower().trim()
)
)
)
)API Reference
Signature
def updateVRef(
selector: Union[str, Dict[str, Any]],
value: Any = None
) -> dScriptParameters:
selector: CSS selector string or dict of {selector: value} pairsvalue: Value to set (string, number, bool, ValueRef, or expression)
Returns:
dScriptobject for use in event handlers
Supported Value Types:
- Literals:
"text",42,True - V() expressions:
V("#source") - Transformations:
V("#input").upper() - Math expressions:
V("#a").int() + V("#b").int() - Boolean expressions:
(V("#age").int() >= 18).then("Adult", "Minor")
Supported Elements:
Input/Textarea: Updates.valuepropertyCheckbox/Radio: Updates.checkedpropertySelect: Updates.valueproperty- Other elements: Updates
.textContent
Integration with Existing Features
With collect_form()
# Collect, validate, and update
form_data = collect_form(
name=V("#name"),
email=V("#email")
)
# Normalize before submit
Button(
"Normalize & Submit",
on_click=sequence(
updateVRef({
"#name": V("#name").trim(),
"#email": V("#email").lower().trim()
}),
form_data.submit("http://localhost:3000/submit")
)
)With Boolean Operators
# Smart updates based on validation
Button(
"Update Status",
on_click=updateVRef("#status",
(V("#email").includes("@")).and_(
V("#password").length() >= 8
).then("✓ Ready", "✗ Incomplete")
)
)With State (Hybrid Approach)
# Local updates for UI
Button("Preview", on_click=updateVRef("#preview",
"Name: " + V("#name") + ", Age: " + V("#age")
))
# Save to global state when ready
user = State("user", name="", age=0)
Button("Save", on_click=sequence(
user.name.set(V("#name")),
user.age.set(V("#age").int())
))When to Use What
Use updateVRef() when:
- Updating UI elements temporarily
- Form auto-fill and normalization
- Local calculations and previews
- Component-level state
- You don't need reactivity across components
Use State.set() when:
- Data needs to persist
- Multiple components need the value
- You need automatic reactivity
- Application-level state
Use both (Hybrid):
- Local updates for immediate feedback
- State updates for persistence
- Best of both worlds!
Bug Fixes
- Fixed edge case in
FormDatawhere nested boolean expressions weren't properly serialized
What's Next
Future enhancements planned for 1.7.0:
useVRef()- Reactive V() expressions with dependenciessetVRef()- Set values accessible via V() selectors- Full exporter integration for reactive bindings
- Enhanced component-level reactivity
Documentation
- Hooks Guide: Updated with updateVRef() examples and use cases
- Operations Guide: Enhanced with updateVRef() integration examples
- Best Practices: Added guidelines for component-level vs global state