Controllers
XWidget allows you to define and register custom controllers to manage business logic and dynamic behaviors within your fragments. Controllers act as the bridge between your fragments and the underlying data or event handling mechanisms.
Creating Controllers
Define controllers in lib/xwidget/controllers/:
import 'package:xwidget/xwidget.dart';
class CounterController extends Controller {
var count = 0;
@override
void bindDependencies() {
dependencies.setValue("count", count);
dependencies.setValue("increment", increment);
}
void increment() {
dependencies.setValue("count", ++count);
}
}
Generating Controller Bindings
To generate controller bindings, run the following command:
This command processes your project’s controller definitions and generates the necessary Dart files to integrate them into your application.
Registering Controllers in Your Application
Once the controllers have been generated, you need to register them during your app’s initialization. Update your main function as follows:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
...
// register XWidget components
registerXWidgetInflaters();
registerXWidgetControllers();
...
}
Using Controllers in Your Fragments
Bind controllers to UI elements:
<Controller name="CounterController">
<!-- listen for changes to 'count' and update children -->
<ValueListener varName="count">
<Text data="${toString(count)}"/>
</ValueListener>
<Button onPressed="${increment}">
<Text>Increment</Text>
</Button>
</Controller>
Controller Lifecycle
- Creation: Controller instance is created via registered factory
- Initialization:
init()method is called (can be async) - Dependency Binding:
bindDependencies()is called - Child Inflation: Child widgets are inflated with access to dependencies
- Build: UI is rendered with controller data
Creating a Controller
Controllers must extend the Controller base class and can override two methods:
init() Method
Called once when the controller is created. Can return:
- void for synchronous initialization
- Future for asynchronous initialization (shows progress widget)
- Stream for streaming data
class MyController extends Controller {
@override
Future<void> init() async {
// Async initialization
await loadData();
}
}
bindDependencies() Method
Called after init() completes. Use this to expose data to the XML markup:
class MyController extends Controller {
List<Product> products = [];
@override
Future<void> init() async {
products = await api.fetchProducts();
}
@override
void bindDependencies() {
dependencies['products'] = products;
dependencies['totalCount'] = products.length;
dependencies['refresh'] = refresh; // Expose method
}
Future<void> refresh() async {
products = await api.fetchProducts();
setState(() {}); // Rebuild UI
}
}
Registering Controllers
Controllers must be registered before use: